python笔记--正则表达式

正则表达式(regular expression)是提取数据时常用的方法,其解析网页的速度比BeautifulSoup库更快。python提供了相关re。

'''
用于提取百度首页中的与百度相关的链接及名称
'''
import re
import requests
from fake_useragent import UserAgent

url = 'https://www.baidu.com/'
ua = UserAgent()
headers = {'User-Agent': ua.random}
html = request.get(url, headers=headers)
html.encoding = 'utf-8'
html = html.text
titles = re.findall(r'<a href="(http://.*?.com)" name="tj_tr.*?" class="mnav">(\w{2})</a>', html)
print(titles)
有时,程序获得的html内容可以和浏览器看到的并不一致。    
具体来说就是,浏览器检查元素看到的内容和网页源码(ctrl+u查看源码)  
是一致的,但是代码获取的内容却不一致,这可能是请求头的问题,  
可以尝试修改请求头再次获取。所以应在解析网页前先打印网页内容查看是否一致,  

findall提供参数:第一个是正则表达式,第二个是带检索的字符串。(1)findall根据正则表达式在字符串里找到所有满足条件的字符串,并将所有结果存储到列表中,之后返回此列表。(2)在正则表达式中为一些字符加上括号,表示想要提取的数据就是括号里面的内容,也就是findall返回的内容。多个括号可以一次提取多个数据,以元祖的形式放在一起。(3)开头字母r,为了避免转义,即不讲正则表达式内的 ‘ \ ‘当作是转义字符。

In [3]: import re

In [4]: string = 'hello\\data\\world'
In [5]: re.findall('\\\\(\w+)\\\\', string)
Out[5]: ['data']
In [6]: re.findall(r'\\(\w+)\\', string)
Out[6]: ['data']

(4).? :‘ . ‘ 在一般情况下表示匹配除了换行符以为的任意字符,当find all中的flag指定为re.DOTALL时,其可以匹配所有字符,包括换行符。‘ ‘表示匹配任意个数的字符,包括0个。‘ ? ‘表示开启非贪婪模式匹配,即尽可能匹配短的字符串。
(5)\w:匹配Unicode字符,一般包括大小写字母,数字和下划线。{2}:表示同时出现两次前面的字符才能匹配。

In [7]: string = 'hello'
In [8]: re.findall('l{2}', string)
Out[8]: ['ll']
In [9]: re.findall('l', string)
Out[9]: ['l', 'l']

小结:BeautifulSoup和正则表达式都是解析网页的工具。前者使用方法简单,且稳定性较强,但是解析速度较慢;后者解析速度快,匹配精确,但是使用方法复杂,稳定性差。

import re
import time
import chardet
import urllib.robotparser
from fake_useragent import UserAgent

def get_headers():
    ua = UserAgent()
    user_agent = ua.random
    headers = {'User-Agent': user_agent}
    return headers

#获取代理IP的函数直接给出了proxies
#也可以用此函数去爬取免费的代理IP
def get_proxies(url ):
    proxies = {
        "http": "125.88.74.122:84"
    }
    return proxies

def get_data(url, num_retries=3, proxies=None):
    try:
        data = requests.get(url, timeout=5, headers=headers)
        print(data.status_code)
    except requests.exceptions.ConnectionError as e:
        print("请求错误, url", url)
        print("错误详情:", e)
        data = None
    except:
        print("未知错误, url", url)
        data = None

    if (data != None) and (500 <= data.status_code < 600):
        if(num_retries > 0):
            print("服务器出错,正在重连...")
            time.sleep(1)
            num_retries -= 1
            get_data(url, num_retries, proxies=proxies)
    return data 

def parse_data(data):
    if data==None:
        return None
    charset = chardet.detect(data.content)
    data.encoding = charset['encoding']
    html_text = data.text
    '''
    对网页数据进行解析提取等操作,假设这里要获取网页的title
    '''
    interesting_data = re.findall('<title>(.*?)</title>', html_text)
    return interesting_data

if '__name__' == '__main__':
    url = "http://www.baidu.com"
    headers = get_headers()
    #此处不是重点,如果运行不出可以注释此语句
    proxies = get_proxies()
    data = get_data(url, num_retries=3, proxies=proxies)
    interesting_data = parse_data(data)
    print(interesting_data)

至此,爬虫添加了异常处理,编码检测,服务器错误重链,动态UA和代理IP功能。

猜你喜欢

转载自blog.csdn.net/weixin_39088580/article/details/82586984