基本库的使用
使用urllib
- urllib是python内置的HTTP请求库,它包含如下的4个模块
- request:它是最基本的HTTP请求模块,可以用来模拟发送请求
- error:异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作以保证程序不会意外终止
- parse:一个工具模块,提供了许多URL处理方法,比如拆分、解析、合并等
- robotparser:主要是用来识别网站的robots.txt文件,然后判断哪些网站可以爬,哪些网站不可以爬,它其实用的比较少
-
发送请求
-
urlopen():urllib.request模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程
- 可以发现,它是一个HTTPresponse类型的对象,可以通过调用read()方法返回网页的内容,调用Status属性可以得到返回结果的状态码
- urlopen()函数的API:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, cadefault=False, context=None )
- data参数:data参数是可选的,需要使用bytes()方法将参数转化为字节流编码格式的内容,即byte类型,另外,如果传递了这个参数,则它的请求方式就不再是GET方式,而是POST方式
- 这里我们传递了一个参数word,值是hello。它需要被转码成bytes(字节流)类型,其中转字节流采用了bytes()方法,该方法的第一个参数需要是str(字符串)类型,需要用urllib.parse模块里的urlencode()方法来将参数字典化成字符串;第二个参数指定编码格式,这里指定为utf8
- timeout参数:用于设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常
- context参数:它必须是ssl.SSLContext类型,用来指定SSL设置
- cafile和capath这两个参数分别指定CA证书和它的路径,这个请求HTTPS链接时会有用
- data参数:data参数是可选的,需要使用bytes()方法将参数转化为字节流编码格式的内容,即byte类型,另外,如果传递了这个参数,则它的请求方式就不再是GET方式,而是POST方式
-
Request:
- 依然是使用urlopen()方法来发送这个请求,只不过这次该方法的参数不再是URL,而是一个Request类型的对象,通过构造这个数据结构,一方面我们可以将请求独立成一个对象,另一方面可更加丰富和灵活的对象
- urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- 第一个参数url用于请求URL,这是必传参数,其他都是可选参数
- 第二个参数data如果要传,必须传bytes(字节流)类型的,如果它是字典,可以先用urllib.parse模块里的urlencode()编码
- 第三个参数headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用实例的add_header()方法添加
- 第四个参数origin_req_host指的是请求方的host名称或者IP地址
- 第五个参数unverifiable表示这个请求是否是无法验证的,默认是False
- 第六个参数method是一个字符串,用来指示请求使用的方法,比如POST, GET, PUT等
-
高级用法:Handler,可以把它理解为各种处理器
- urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法、例如default_open()等
- HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常
- HTTPRedirectHandler:用于处理重定向
- HTTPCookieProcessor:用于处理Cookies
- ProxyHandle:用于设置代理、默认代理为空
- HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表
- HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题
- urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法、例如default_open()等
-
OpenerDirector,可以称为Opener:
- Opener可以使用open()方法,返回类型和urlopen()一样,但是功能更全,利用Handler来构建Opener
- 验证
- 这里首先实例化HTTPBasicAuthHandler对象,其参数是HTTPPasswordMgrWithDefaultRealm对象,它利用add_password() 添加进去用户名和密码,这样就建立了一个处理验证的Handler
- 接下来,利用这个Handler并使用build_opener()方法构建一个Opener,这个Opener在发送请求时相对于已经验证成功
- 接下来,利用Opener的open()方法打开链接,就可以完成验证了
- 代理
- 这里我们在本地搭建了一个代理,它运行在9743端口上
- 这里使用了ProxyHandler,其参数是一个字典,键名是协议类型,键值是代理链接,可以添加多个代理
- 然后利用这个Handler及build_opener()方法构造一个Opener,之后发送请求即可
-
Cookies
- 首先要声明一个CookieJar对象
- 接下来就需要利用HTTPCookieProcessor来构建一个Handler
- 最后利用build_opener()方法构建出Opener,执行open()函数即可
-
处理异常
- urllib的error模块定义了由request模块产生的异常,如果出现了问题,request模块便会抛出error模块中定义的异常
- URLError
- URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,由request模块产生的异常都可以通过捕获这个类来处理
- 他有一个属性reason,即返回错误的原因
- 打开了一个不存在的页面,照理来说应该会报错,但是捕获了URLError这个异常
- HTTPError
- 它是URLError的子类,专门用来处理HTTP请求错误,比如认证请求失败等,它有如下3个属性
- code:返回HTTP状态码
- reason:同父类一样,用于返回错误的原因
- headers:返回请求头
- 有时候reason属性返回的不一定是字符串,也可能是一个对象
-
解析链接
- urlparse(),该方法可以实现URL的识别和分段
- 这里我们利用urlparse()方法进行了一个URL的解析
- 可以看到,返回结果是一个ParseResult类型的对象,它包含6个部分,分别是scheme、netloc、path、params、query和fragment
- 获取格式:scheme://netloc/path;params?query#fragment
- API:urllib.parse.urlparse(urlstring, scheme=’’, allow_fragments=True)
- urlstring:这是必填项,即带解析的URL
- scheme:它是默认的协议(比如http或https等),加入这个链接没有带协议信息,会将这个作为默认的协议,所以scheme参数只有在URL中不包含scheme信息时才生效
- allow_fragments:即是否忽略fragment,如果它被设置为False,fragment部分就会被忽略,它会被解析为path、parameters或者query的一部分,而fragment部分为空
- ParseResult可以用索引顺序来获取,也可以用属性名获取
- urlunparse():用于构造URL
- 它接受的参数时一个可迭代对象,但是它的长度必须是6
- 它接受的参数时一个可迭代对象,但是它的长度必须是6
- urlsplit():这个方法跟urlparse()方法非常相似,只不过它不再单独解析params这一部分,只返回5个结果
- 返回结果时SplitResult,也可以用属性获取值,也可以用索引来获取
- urlunsplit():与urlunparse()类似,传入的参数也是一个可迭代对象,唯一的区别时长度必须为5
- urljoin():
- urljoin()需要提供一个base_url(基础链接)作为第一个参数,将新的链接作为第二个参数
- 该方法会分析base_url的scheme、netloc和path这3个内容并对新链接缺失的部分进行补充,最后返回结果
- base_url提供了三项内容scheme、netloc和path,如果这3项在新的链接里不存在就予以补充;如果新的链接存在,就使用新的链接的部分。而base_url中的params、query和fragment是不起作用的
- urlencode():用来转化URL参数(序列化)
- 该方法在构造GET请求参数的时候非常有用,为了更加方便地构造参数,会事先用字典来表示,再调用该方法即可
- parse_qs():如果有一串GET请求参数,利用parse_qs()方法,就可以将它转回字典,反序列化
- parse_qsl():用于将参数转化为元组组成的列表
- 运行结果是一个列表,而列表中的每一个元素都是一个元组,元组的第一个内容是参数名,第二个内容是参数值
- quote():可以将内容转化为URL编码的格式,URL中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为URL编码
- unquote():可以进行URL解码
- urlparse(),该方法可以实现URL的识别和分段
-
Robots协议
- Robots协议
- Robots协议也称作爬虫协议,机器人协议,它的全名叫做网络爬虫排除标准,用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取,它通常是一个叫做robots.txt的文本文件,一般放在网站的根目录下
- User-agent参数描述了搜索爬虫的名字,这里将其设置成*则代表该协议对任何爬取爬虫有效,否则只有所设置的名称才可以爬取
- Disallow指定了不允许抓取的目录,比如设置为/则代表不允许抓取所有页面
- Allow一般和Disallow一起使用,一般不会单独使用,用来排除某些限制,比如Disallow设置为/,Allow设置为/public/,则表示所有页面不允许抓取,但可以抓取public目录
- robotparser:解析robots.txt,该模块提供了一个类RobotFIleParser,它可以根据某网站的robots.txt文件来判断一个爬取爬虫是否有权限
- 该类用起来非常简单,只需要在构造函数方法里传入robots.txt的链接即可,或是使用set_url() 方法,以下就是这个类常用的方法
- set_url():用来设置robots.txt文件的链接
- read():读取robots.txt文件并进行分析,注意,这个方法执行一个读取和分析操作,如果不调用这个方法,接下来的判断都会为False,所以一定记得调用这个方法,这个方法不会返回任何内容,但是执行了读取操作
- parse():用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容
- can_fetch():该方法传入两个参数,第一个是User-agent,第二个是要抓取的URL,发挥的内容是该搜索引擎是否可以抓取这个URL,返回结果是True或False
- mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,你科恩那个需要定期检查来抓取最新的robots.txt
- modified():它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间
- 首先创建RobotFIleParser对象
- 然后通过set_url()方法设置了robots.txt的链接
- 接着利用can_fetch()方法判断了网页是否可以被抓取
- Robots协议
-
使用requests
- GET请求
- 基本实例
- 使用get()方法发出请求,得到一个Response对象
- 可以将信息数据用字典来存储,然后通过添加params属性来添加URL的参数
- 网页的返回类型实际上是str类型的,但是确实JSON格式的,所以可以调用json()方法从而得到一个字典,但是如果返回结果不是JSON格式,就会出现错误,抛出json.decoder.JSONDecodeError异常
- 使用get()方法发出请求,得到一个Response对象
- 抓取网页
- 抓取二进制数据
- 图片、音频、视频这些文件本质上都是由二进制码组成的
- 这里使用了open()方法,他的第一个参数是文件名称,第二个参数代表以二进制写的形式打开,可以向文件里写入二进制文件
- 原理:就是将二进制数据以二进制的形式写入文件中
- 添加header
- 与urllib.request一样,也可以通过headers参数来传递头信息
- 基本实例
- POST 请求
- 发出请求:使用requests.post( )
- 高级用法
- 文件上传:
- favicon.ico需要和当前脚本在同一目录下
- 就是利用了post()方法的files参数
- Cookies:
- 首先调用cookies属性即可成功得到Cookies,可以发现它是RequestCookieJar类型
- 然后用items()方法将其转化为元组组成的列表
- 接着便利输出每一个Cookie的名称和值,实现Cookie的遍历解析
- 也可以自行添加headers,只需要在get()方法里添加headers参数
- 会话维持:由于利用get()方法或post方法都是相当于用浏览器打开页面,所以很难保持下一次打开状态还在,这时候就需要会话维持了
- 需要使用Session对象
- 我们请求了一个测试网址,请求这个网址的时候设置了一个cookie,名称叫做number,内容是123456,随后又请求了http://httobin.org/cookies,此网址可以获取当前的cookie
- 利用Session,可以做到模拟同一个会话而不用担心Cookies的问题,它通常用于模拟登陆成功之后再进行下一步的操作
- SSL证书验证
- requests还提供了证书验证的功能,当发送HTTP请求的时候,它会检查SSL证书
- 可以使用verify参数控制是否检查此证书,如果不加这个参数的话,默认为True
- 代理设置
- 需要使用proxies参数来进行设置代理
- 若代理需要使用HTTP Basic Auth,可以使用类似http://user:password@host:port这样的语法来设置代理
- 超时设置
- 为了复制服务器不能及时响应,应该设置一个超时时间,这需要用到timeout参数,这个时间计算是发出请求到服务器返回响应的时间,示例如下
- 实际上,请求分为两个阶段,即连接和读取,上面设置的timeout将用作连接和读取这二者的tiemout总和
- 如果想永久等待,可以直接将timeout设置为None,或者不设置直接留空
- 为了复制服务器不能及时响应,应该设置一个超时时间,这需要用到timeout参数,这个时间计算是发出请求到服务器返回响应的时间,示例如下
- 身份认证
- 如果用户名和密码正确的话,请求时就会自动认证成功,会返回200状态码,如果认证失败,则返回401
- 参数可以传一个HTTPBasicAuth类,也可以传一个元组,它会默认使用HTTPBasicAuth这个类来认证
- Prepared Request
- 前面介绍urllib时,我们可以将请求表示为数据结构,其中各个参数都可以通过一个Request对象来表示,这在requests里同样可以做到,这个数据结构就叫Prepared Request
- 这里我们引入了Request,然后用url、data和headers参数构造了一个Request对象
- 这时需要再调用Session的prepare_request()方法将其转换为一个Prepared Request对象,然后调用send()方法发送即可
- 文件上传:
正则表达式
- python的re库提供了整个正则表达式的实现,利用这个库可以在python中使用正则表达式
- match()
- 向它传入要匹配的字符串与正则表达式,match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果,如果不匹配,就返回None,一旦开头不匹配,那么整个匹配就失败了,实例如下
- 在match()方法中,第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串
- 结果是SRE_Match对象,该对象有两个方法:group()方法可以输出匹配到的内容,span()方法可以输出匹配的范围,这是匹配到的结果字符串在原字符串中的位置范围
- 向它传入要匹配的字符串与正则表达式,match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果,如果不匹配,就返回None,一旦开头不匹配,那么整个匹配就失败了,实例如下
- 匹配目标
- 可以使用**()括号将想提取的子字符串括起来,()实际上标记了一个子表达式的开始和结束位置,被标记的每个子表达式会依次对应**每一个分组
- 可以使用group()方法传入分组的索引即可获取对应组的结果,group(1)和group()有所不同,后者会输出完整的匹配结果,而前者会输出第一个被()包围的匹配结果
- 通用匹配
- 万能匹配:.*
- 贪婪与非贪婪
- 在贪婪模式下,.*会匹配尽可能多的字符
- 非贪婪就是匹配尽可能少的字符,字符串中间尽量使用非贪婪匹配,但是要注意,如果放在了结尾,就有可能匹配不到任何内容了
- 修饰符
- 正则表达式可以包含一些可选标志修饰符来控制匹配的模式
- re.I:使匹配对大小写不敏感
- re.L:做本地化识别匹配
- re.M:多行匹配,影响^和$
- re.S:使 . 匹配包括换行在内的所有字符
- re.U:根据Unicode字符集解析字符,这个标志影响\w,\W,\b和\B
- re.X:该标志通过给予你更灵活的格式以便你将正则表达式写的更易于理解
- 转义匹配
- 由于 . 表示匹配所有出了换行符的字符,而如果就想要匹配 . 这个字符的话,需要在.前加个**反斜线**,.就代表匹配.符号
- search()
- 它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果
- 正则表达式可以是字符串的一部分,如果搜索完了还没有找到,就返回None
- findall()
- 该方法会搜索整个字符串,然后返回匹配正则表达式的所有内容
- 如果有返回类型的话,就是列表类型,发挥的列表中的每个元素都是元组类型
- sub()
- 用于替换字符
- 第一个参数传入正则表达式来匹配字符,第二个参数为替换成的字符串,第三个参数使原字符串
- compile()
- 这个方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用
- compile()还可以传入修饰符,这样在search(),findall()等方法中就不需要额外传了