3.基本库的使用
3.1 Urllib
是 Python 内置的 HTTP 请求库
- request :最基本的 HTTP 请求模块,我们可以用它来模拟发送一请求,就像在浏览器里输入网址然后敲击回车一样,只需要给库方法传入 URL 还有额外的参数,就可以模拟实现这个过程了。方便地实现 Request 的发送并得到 Response
- error :即异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作保证程序不会意外终止
- parse :一个工具模块,提供了许多 URL 处理方法,比如拆分、解析、合并等等的方法
- robotparser:主要是用来识别网站的 robots.txt 文件,然后判断哪些网站可以爬,哪些网站不可以爬的,实际用的比较少
- urlopen()
urllib.request.urlopen()函数用于实现对目标url的访问。
import urllib.request
response = urllib.request.urlopen('https://www.python.org') #response是一个HTTPResposne类型的对象
print(response.read().decode('utf-8')) #直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。
print(response.status) #响应的状态码
print(response.getheaders()) #响应的头信息
print(response.getheader('Server')) #获取 headers 中的 Server 值
函数原型:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- url: 需要打开的网址
- data:Post提交的数据
data 参数是可选的,如果要添加 data,它要是字节流编码格式的内容,即 bytes 类型,通过 bytes() 方法可以进行转化,另外如果传递了这个 data 参数,它的请求方式就不再是 GET 方式请求,而是 POST
import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
传递了一个参数 word,值是 hello。它需要被转码成bytes(字节流)类型。其中转字节流采用了 bytes() 方法,第一个参数需要是 str(字符串)类型,需要用 urllib.parse 模块里的 urlencode() 方法来将参数字典转化为字符串。第二个参数指定编码格式,在这里指定为 utf8。
- timeout:设置网站的访问超时时间,单位为秒,意思就是如果请求超出了设置的这个时间还没有得到响应,就会抛出异常,如果不指定,就会使用全局默认时间。它支持 HTTP、HTTPS、FTP 请求。
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())
#通过设置这个超时时间来控制一个网页如果长时间未响应就跳过它的抓取
import socket
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
- cafile、capath、cadefault 参数:用于实现可信任的CA证书的HTTP请求。(基本上很少用)
- context参数:实现SSL加密传输,必须是 ssl.SSLContext 类型。(基本上很少用)
直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。
- Request
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- url 参数:请求的 URL,这个是必传参数,其他的都是可选参数。
- data 参数:必须传 bytes(字节流)类型的,如果是一个字典,可以先用 urllib.parse 模块里的 urlencode() 编码
- headers 参数是一个字典,这个就是 Request Headers 了,你可以在构造 Request 时通过 headers 参数直接构造,也可以通过调用 Request 实例的 add_header() 方法来添加。伪装火狐浏览器:Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11
- origin_req_host 参数指的是请求方的 host 名称或者 IP 地址
- unverifiable 参数:这个请求是否是无法验证的,默认是False。例如我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。
- method 参数是一个字符串,它用来指示请求使用的方法,比如GET,POST,PUT
from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
'Host': 'httpbin.org'
}
dict = {
'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
通过四个参数构造了一个 Request,url 即请求 URL,在headers 中指定了 User-Agent 和 Host,传递的参数 data 用了 urlencode() 和 bytes() 方法来转成字节流,另外指定了请求方式为 POST。
- 高级用法
各种处理器,有专门处理登录验证的,有处理 Cookies 的,有处理代理设置的,利用它们我们几乎可以做到任何 HTTP 请求中所有的事情。
- urllib.request 模块里的 BaseHandler类
是所有其他 Handler 的父类,它提供了最基本的 Handler 的方法,例如 default_open()、protocol_request() 方法等。
接下来就有各种 Handler 子类继承这个 BaseHandler 类,举例几个如下:
HTTPDefaultErrorHandler 用于处理 HTTP 响应错误,错误都会抛出 HTTPError 类型的异常。
HTTPRedirectHandler 用于处理重定向。
HTTPCookieProcessor 用于处理 Cookies。
ProxyHandler 用于设置代理,默认代理为空。
HTTPPasswordMgr 用于管理密码,它维护了用户名密码的表。
HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。
另外还有其他的 Handler 类,在这不一一列举了,详情可以参考官方文档: https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler - OpenerDirector
我们可以称之为 Opener,我们之前用过 urlopen() 这个方法,实际上它就是 Urllib为我们提供的一个 Opener。Opener 可以使用 open() 方法,返回的类型和 urlopen() 如出一辙,Opener是利用 Handler 来构建的。
- 认证
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = 'username'
password = 'password'
url = 'http://localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p) #例化了一个 HTTPBasicAuthHandler 对象,参数是 HTTPPasswordMgrWithDefaultRealm 对象,它利用 add_password() 添加进去用户名和密码,这样我们就建立了一个处理认证的 Handler。
opener = build_opener(auth_handler) #利用 build_opener() 方法来利用这个 Handler 构建一个 Opener,那么这个 Opener 在发送请求的时候就相当于已经认证成功
try:
result = opener.open(url) #利用 Opener 的 open() 方法打开链接,就可以完成认证了,在这里获取到的结果就是认证后的页面源码内容。
html = result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)
- 代理
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
'http': 'http://127.0.0.1:9743',
'https': 'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
在此本地搭建了一个代理,运行在 9743 端口上。
在这里使用了 ProxyHandler,ProxyHandler 的参数是一个字典,键名是协议类型,比如 HTTP 还是 HTTPS 等,键值是代理链接,可以添加多个代理。
然后利用 build_opener() 方法利用这个 Handler 构造一个 Opener,然后发送请求即可。
3. Cookies
Cookies 的处理就需要 Cookies 相关的 Handler 了。
import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar() #声明一个 CookieJar 对象
handler = urllib.request.HTTPCookieProcessor(cookie) #利用 HTTPCookieProcessor 来构建一个 Handler
opener = urllib.request.build_opener(handler) #利用 build_opener() 方法构建出 Opener
response = opener.open('http://www.baidu.com') #执行 open() 函数
for item in cookie:
print(item.name+"="+item.value)