urllib
python内置HTTP请求库,包含四个模块:
发送请求
使用urllib.request模块,可以模拟一个浏览器发送请求并取得回应。
import urllib.request
response = urllib.request.urlopen(url)
print(response.read().decode('utf-8'))
得到响应后使用read()方法读取其内容,utf-8解码后可以得到内容。
得到的response是一个HTTPResponse类型对象,包含read(), readinto(), getheader(name), getheaders(), fileno()等方法,以及msg, version, status, reason, debuglevel, closed等属性。
status:得到响应的状态码。
getheaders():得到响应头。
getheader(‘Server’):获取响应头中的某一值。
…
urlopen()除了url以外,还可以传递其他参数
*data:可选参数,添加这个参数后请求方式为POST,data即为要传递的数据,使用bytes()方法将要传递的参数转化为字节流编码格式的内容。
from urllib import request, parse
data = bytes(parse.urlencode({'word': 'hello'}), encoding='utf-8')
response = request.urlopen(url, data=data)
print(response.read())
*timeout
设置超时时间,单位是秒。如果超出请求时间还没有得到响应就抛出异常,如果不指定该参数,使用全局默认时间。
import urllib.request
response = urllib.request.urlopen(url, timeout=1)
print(response.read())
可以利用设置超时时间,跳过抓取长时间未响应的网站。
import socket
from urllib import request, error
try:
response = request.urlopen(url, timeout=1)
except error.URLError as e:
if isintance(e.reason, socket.timeout):
print('TIME OUT')
isinstance()类似type(),判断一个对象是否是已知类型,会考虑继承关系,认为子类是一种父类类型。
*其他参数
context:它必须是SSLContext类型,用来指定SSL设置;cafile, capath这俩个参数分别指定CA证书和它的路径,在请求HTTPS链接有用。
Request
urlopen()可以实现最基本的请求,如果要加入更多的信息,可以使用Request类。
依然使用urlopen()发送请求,但是其参数是一个Request类的对象,该对象可以灵活的配置信息,构成一个独立的请求对象。
from urllib import request
request = request.Request(url)
response = request.urlopen(request)
print(response.resd().decode('utf-8'))
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
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='utf-8'))
req = request.Request(url=url, headers=headers, data=data, method='POST')
response = resquest.urlopen(req)
print(response.read().decode('utf-8'))
req = request.Request(url=url, data=data, method=‘POST’)
req.add_header(‘User-Agent’: ‘Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)’)
Handler
各种Handler类似各种处理器,可以处理不同的事情。
urllib.request里面的BaseHandler,是其他所有Handler的父类,提供最基本的方法。
官方文档:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler
OpenerDirector,成为Opener,urlopen()就是urllib提供的一个Opener,Opener可以实现更高级的功能,深入一层进行配置,使用更底层的实例完成操作。
Opener可以使用open()方法,返回类型和urlopen()一样。
利用Handler来构建Opener
添加代理
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
#使用proxy_handler添加代理
proxy_handler = ProxyHandler({
'http': 'http://代理'
'https': 'https://代理'
})
opener = build_opener(proxy_handler)
try:
response = opener.open(url)
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
这里使用了Proxy_Handler,参数是一个字典,键名是协议类型,键值是代理链接。
Cookies
先将网站的Cookies获取下来:
#导入库
import http.cookiejar, urllib.request
#声明一个CookieJar对象
cookie = http.cookiejar.CookieJar()
#利用HTTPCooikeProcessor构建一个Handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#构建一个opener
opener = urllib.request.build_opener(handler)
#使用opener打开链接
response = opener.open(url)
#将cookies逐条打印出来
for item in response:
print(item.name+"="+item.value)
结果会输出每条Cookie的名称和值,也可以输出为文件格式。
filename = 'cookies.text'
#声明一个MozillaCookieJar对象
cookie = urllib.cookiejar.MozillaCookieJar(filename)
#构建一个Handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#创建opener()
opener = urllib.request.build_opener(handler)
response = opener.opern(url)
#保存,参数表示忽略丢弃,忽略失效
cookie.save(ignore_discard=True, ignore_expires=True)
声明对象变为MozillaCookieJar,在生成文件的时候会用到,是CookieJar的子类,可以处理Cookies和文件的相关事件。
LWPCookieJar也可以保存和读取Cookies,但是保存格式不是text,而是LWP格式的Cookies文件。
保存之后的读取
cookie = http.cookiejar.LWPCookieJar()
#用load读取
cookie.load('cookies.text', ignore_discard=True, ignore_expires=True)
#使用读取后的cookie建立handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#创建opener
opener = urllib.request.build_opener(handler)
#使用这个opener打开URL,会带上之前的cookie
response = opener.open(url)
print(response.read().decode('utf-8')
参考官方文档:
https://docs.python.org/3/library/urllib.request.html#basehandler-objects
异常处理
from urllib import request, error
try:
response = request.urlopen(url)
except error.URLError as e:
print(e.reason)
from urllib import request, error
try:
response = request.urlopen(url)
except error.HTTPError as e:
print(e.reason)
except error.URLError as e:
print(e.reason)
else:
print('error')
可以获得更详细的出错信息。
解析链接
urllib.parse.urlparse()
这个方法可以实现URL的识别和分段
from urllib.parse import urlparse
result = urlparse("http://www.baidu.com/index.html;user?id=5#comment")
print(type(result), result)
运行结果:
ParseResult(scheme='http', netloc='www.baidu.com', path='index.html', params='user', query='id=5', fragment='comment')
使用urlparse()将URL拆分为6部分:
API用法:
urllib.parse.urlparse(urlstring, scheme=’’, allow_fragment=True)
urlunparse()
urlparse的对立方法,接受一个可迭代对象为参数,但是长度必须是6:
from urllib.parse import urlunparse
data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
print(urlunparse(data))
结果为:http://www.baidu.com/index.html;user?a=6#comment
urlsplit()
类似urlparse(),只是不再单独解析params这一部分,值返回5个结果。
urlunsplit()
和urlunparse()类似,也是将链接的各个部分整合在一起,长度为5
urljoin()
也用于生成新链接,提供一个base_url(基础链接)作为第一个参数,新链接为第二个参数,该方法会将base_url的scheme、netloc、path这3个内容并对新连接的缺失部分进行补充,返回结果。
from urllib.parse import urljoin
base_url = 'http://www.baidu.com'
aim_url = 'FAQ.html'
result = urljoin(base_url, aim_url)
print(result)
结果是:
http://www.baidu.com/FAQ.html
base_url提供三项内容:scheme, netloc, path,新连接中如果没有就补充,如果新连接有,就不变。
urlencode()
常用方法之一,构造GET请求参数的时候很有用:
from urllib.parse import urlencode
params = {
'name': 'germey',
'age': 22
}
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(params)
print(url)
结果为:http://www.baidu.com?name=germey&age=22
为了更方便的构造参数,可以事先用字典表示,转为URL参数时,调用这个方法即可。
parse_qs()
反序列化,urlencode()的对立
from urllib.parse import parse_qs
query = 'name=germey&age=22'
print(parse_qs(query))
结果为:
{‘name’: [‘germey’], ‘age’: [‘22’]}
使用parse_qsl()转化为元组的形式
结果为:
[(‘name’: ‘germey’), (‘age’: ‘22’)]
结果是一个列表,里面每一个元素都是一个元组。
quote()
将内容转化为URL编码格式,带有中文参数的时候可能会导致乱码,使用quote()方法,可以将中文也转化为编码格式。
from urllib.parse import quote
keyword = "大熊猫"
url = 'https://www.baidu.com/s?wd=' + quote(keyword)
print(url)
unquote()
quote()方法的对立,可对中文进行解码。