使用urrlib
是python的内置的HTTP请求库
python3不存在urllib2的说法,统一为urllib*
包括如下四个模块:
- request
它是最基本的HTTP请求模块,可以用来模拟发送请求。就像在浏览器里输入网址
然后回车一样,只需要给库方法传入U R L 以及额外的参数,就可以模拟实现这个过程了
- error
异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操
作以保证程序不会意外终止
- parse
一个工具模块,提供了许多URL处理方法,比如拆分、解析 、合并等
- robotparser
主要是用来识别网站的robots.txt文件,然后判断哪些网站可以爬,哪些网站不
可以爬,它其实用得比较少。
发送请求
使 用 urllib的 request模块,我们可以方便地实现请求的发送并得到响应
urlopen()
urllib .request模 块 提 供 了 最 基 本 的 构 造HTTP请 求 的 方 法 ,利用它可以模拟浏览器的一个请求发 起 过 程 ,同 时 它 还 带 有 处 理授 权 验 证 (authenticaton )、重 定 向 (redirection)、 浏 览 器 Cookies以及其他内容 。
请求方法urllib.request
1 | import urllib.request |
响应response常用方法
response是一个 HTTPResposne 类 型 的 对 象 ,主要包含 read(), readinto(), getheader(name),getheaders(), fileno ()等 方 法 ,以及 msg、 version, status, reason, debuglevel, closed 等 属 性 。
- read()
获取响应体
- status
响应状态码
- getheaders()
获取响应头
- getheaders(‘server’)
输入参数server,返回服务器类型
链接传参
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- data
data参数是可选的。如果要添加该参数,并且如果它是字节流编码格式的内容,即 bytes类型,则需要通过bytes()方法转化。另外,如果传递了这个参数,则它的请求方式就不再是GET方式,而是 POST方式
1 | import urllib.parse |
http://httpbin.org提供HTTP测试
http://httpbin.org/post提供POST测试
- timeout
timeout参数用于设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常。如果不指定该参数,就会使用全局默认时间。
超时报urllib.error.URLError
使用try except:
1 | import socket |
- 其它参数
context
它必须是ssl.SSLContext类型,用来指定SSL设置
cafile和capath
这两个参数分别指定C A 证书和它的路径,这个在请求HTTPS链接时会
有用
Request
urlopen只能用于简单的请求
1 | import urllib.request |
可以发现,我们依然是用urlopen()方法来发送这个请求,只不过这次该方法的参数不再是URL,而是一个Request类型的对象。通过构造这个数据结构,一方面我们可以将请求独立成一个对象,另一方面可更加丰富和灵活地配置参数。
构造请求
*urllib.request.Request(url, data=None, headers={},origin_req_host=None, unverifiable=False, method=None) *
- data
data 如果要传,必须传bytes (字节流 )类型的 。如果它是字典,可以先用
urllib.parse 模块里的 urlencode()编码
- headers
headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加。
添加请求头最常用的用法就是通过修改User-Agent来伪装浏览器,默 认 的 User-Agent是Python-urllib,我们可以通过修改它来伪装浏览器。比如要伪装火狐浏览器,你可以把它设置为:
Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11
- origin_req_host
origin_req_host指的是请求方的host名称或者IP 地址
- unverifiable
unverifiable表示这个请求是否是无法验证的,默认是F a ls e ,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这 时 u nverifiable的值就是True。
- method
method是一个字符串,用来指示请求使用的方法,比如GET、 POST和 PUT等。
1 | import urllib.request |
高级用法
Handler
[handler官方文档](https://docs.python.
org/3/library/urllib.request.html#urllib.request.BaseHandlero )
上面无法处理代理,cookies的情况
简而言之,我们可以把它理解为各种处理器, 有专门处理登录验证的,有处理 Cookies的,有处理代理设置的。利用它们,我们几乎可以做到HTTP请求中所有的事情。
首先,介绍一下urllib.request模块里的BaseHandler类 ,它是所有其他Handler的父类, 它提供了最基本的方法,例如 default_open(). protocol_request()等。
有各种Handler子类继承这个BaseHandler类,举例如下 :
□ HTTPDefaultErrorHandler: 用于处理HTTP响应错误,错误都会抛岀HTTPError类型的异常。
□ HTTPRedirectHandler: 用于处理重定向。
□ HTTPCookieProcessor: 用于处理 Cookies
□ ProxyHandler: 用于设置代理,默认代理为空。
□ HTTPPasswordMgr: 用于管理密码,它维护了用户名和密码的表。
□ HTTPBasicAuthHandler: 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。
OpenerDirector
那么,为什么要引入Opener呢?因为需要实现更高级的功能。之前使用的Request和 urlopen()相当于类库为你封装好了极其常用的请求方法,利用它们可以完成基本的请求,但是现在不一样了,我们需要实现更高级的功能,所以需要深入一层进行配置,使用更底层的实例来完成操作,所以这里就用到了 0pener
当打开网页弹出提示框要求输入密码,账号时:
1 | from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener |
代理
1 | from urllib.error import URLError |
Cookies
Cookies的处理就需要相关的Handler 了
1 | import http.cookiejar, urllib.request |
处理异常
URLError
1 | from urllib import request, error |
HTTPError
它是URLError的子类,专门用来处理HTTP请求错误
有如下三个属性:
- code
返 回 HTTP状态码,比如404表示网页不存在, 500表示服务器内部错误等。
- reason
同父类一样,用于返回错误的原因。
- headers
返回请求头。
解析链接
前面说过, urllib库里还提供了 parse模 块 ,它定义了处理URL的标准接口,例如实现URL各部分的抽取、合并以及链接转换。它支持如下协议的URL处 理 : file, ftp、 gophers hdl、 http、 https、 imap、
mailto、 mms、 news、 nntp、 prosper。、 rsync、 rtsp、 rtspu、 sftp、 sip、 sips、 snews、 svn、 svn+ssh. telnet和 wais
urlparse()
1 | from urllib.parse import urlparse |
可以看到,返回结果是一个ParseResult类型的对象,它 包 含 6 个部分,分另U是 scheme, netloc.path、 param, squery, fragment
result可以用元组的概念,也可以用属性来获取各部分
1 | print(result[0], result.params) |
urlparse API
urllib.parse.urlparse(urlstring, scheme=’ ‘, allow_fragments=True)
- urlstring
- scheme
当传入的url没有协议时,可以指定scheme参数为http/https
当本身就有协议,有传参为不同的协议,则会输出本身的协议
- allow_fragments
设置为false时,结果就不会有fragments这一部分
当参数为false且链接中没有params和query时,fragment便会解析为path内容的一部分
urlunparse()
与urlparse()相反
1 | from urllib.parse import urlunparse |
urlsplit()
这个方法和urlparse()方法非常相似,只不过它不再单独解析params这一部分,只返回5 个结果。上面例子中的params会合 并 到 path中。
1 | from urllib.parse import urlsplit |
urlunsplit()
与 urlunparse()类似,它也是将链接各个部分组合成完整链接的方法,传入的参数也是一个可迭代对象,例如列表、元组等,唯一的区别是长度必须为5。
urljoin()
有了 urlunparse()和 urlunsplit()方 法 ,我们可以完成链接的合并,不过前提必须要有特定长度的对象,链接的每一部分都要清晰分开。
生成链接还有另一个方法,那 就 是 urljoin()方法。我们可以提供一个base_url (基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析base_url的 scheme, netloc和 path这 3个内容并对新链接缺失的部分进行补充
1 | from urllib.parse import urljoin |
可以发现, base_url提供了三项内容scheme, netloc和 path。 如果这3 项在新的链接里不存在,就予以补充;如果新的链接存在,就使用新的链接的部分。而 base_url中的 params、 query和 fragment
是不起作用的。
urlencode()
它 在 构 造 GET请求参数的时候非常有用
1 | from urllib.parse import urlencode |
parse_qs()
有了序列化,必然就有反序列化。如果我们有一串GET请求参数,利 用 parse_qs()方 法 , 就可以将它转回字典,示例如下
1 | from urllib.parse import parse_qs |
parse_qsl()
另外,还 有 一 个 parse_qsl()方 法 ,它用于将参数转化为元组组成的列表
1 | from urllib.parse import parse_qsl |
quote()
该方法可以将内容转化为U RL编码的格式。 U R L 中带有中文参数时,有时可能会导致乱码的问题 ,此时用这个方法可以将中文字符转化为URL编码
1 | from urllib.parse import quote |
unquote()
有了 quote。 方法,当然还有unquote()方法,它可以进行URL解 码
1 | from urllib.parse import unquote |
分析Robots协议
Robots协议
Robots协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准( Robots Exclusion Protocol) , 用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作robots.txt
的文本文件,一般放在网站的根目录下
robots.txt文件可以为空
一个爬虫爬取一个网站时,首先会看是否存在robots.txt,然后在按内容爬取;如果不存在则直接爬取
Allow 一 般 和 Disallow 一 起 使 用 ,一般不会单独使用
- 禁止所有爬虫爬取任何目录
User-agent: *
Disallow: /
- 允许所有爬虫爬取任意目录
User-agent: *
Disallow:
- 禁止所有爬虫爬取某些目录
User-agent: *
Disallow: /private/
Disallow: /tmp/
- 只允许某一个爬虫爬取爬取
User-agent: Webcrawler
Disallow:
User-agent: *
Disallow: /
爬虫名称
大家可能会疑惑,爬虫名是哪儿来的?为什么就叫这个名?其实它是有固定名字的了,比如百度的就叫作BaiduSpider
robotparser
*了 解 Robots协议之后, 我们就可以使用robotparser模块来解析robots.txt 了。该模块提供了一个类 R obotFileParser,它可以根据某网站的robots.txt文件来判断一个爬取爬虫是否有权限来爬取这个
1 | urllib.robotparser.RobotFileParser(url) |
这个类常用方法:
set_url
实例化这个类时传入了url,就不需要这个方法了
read()
读 取 robots.txt文件并进行分析。注意,这个方法执行一个读取和分析操作,如果不调用这个方法,接下来的 判 断 都 会 为F a ls e ,所以一定记得调用这个方法。这个方法不会返回任何内容,但是执行了读取操作。
直接传入url和set_url()需要执行read(), 使用parse()不需要使用
parse()
用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容。
传入的可以是数组,元组
can_fetch()
该方法传入两个参数,第一个是U ser-agent,第二个是要抓取的URL。 返回的内容是该搜索引擎是否可以抓取这个U R L ,返回结果是True或 False。
mtime()
该方法传入两个参数,第一个是U ser-agent,第二个是要抓取的URL。 返回的内容是该搜索引擎是否可以抓取这个U R L ,返回结果是True或 False。
modified()
它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间。
使用can_fetch()
1 | from urllib.robotparser import RobotFileParser |
使用parse()
1 | from urllib.robotparser import RobotParser |
问候不一定要郑重其事,但一定要真诚感人。
