urllib.request模块提供了最基本的构造HTTP请求方法,利用 它可以模拟浏览器的一个请求发起过程 ,同时它还带有处理授权验证(authentication)、重定向(redirection)、浏览器Cookies以及其他内容。
案例:Python官网爬取:
import urllib.request
respose = urllib.request.urlopen('https://www.python.org/')
print(respose.read().decode('utf-8'))
运行结果(部分):
以上几行代码完成了python官网的抓取,输出网页的源代码。得到源代码以后我们想要的链接、图片地址、文本信息就可以提取出来了。
利用type()方法查看返回结果是啥:
import urllib.request
respose = urllib.request.urlopen('https://www.python.org/')
print(type(respose))
运行结果:
返回了一个HTTPResponse类型的对象,主要包括read()、readinto()、getheader(name)、getheaders()、fileno()等方法以及msg、version、status、reason、debuglevel、closed等属性。
read()方法可以返回得到网页内容,调用status属性可以得到返回结果的状态码,200代表请求成功,404代表网页未找到(服务器内没有这个网页数据)
import urllib.request
response = urllib.request.urlopen('https://www.python.org/')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
运行结果:
200
[('Connection', 'close'), ('Content-Length', '50007'), ('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur, 1.1 varnish, 1.1 varnish'), ('Accept-Ranges', 'bytes'), ('Date', 'Sat, 24 Oct 2020 02:38:15 GMT'), ('Age', '2076'), ('X-Served-By', 'cache-bwi5128-BWI, cache-sna10736-LGB'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '2, 1'), ('X-Timer', 'S1603507096.581736,VS0,VE1'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
nginx
以上只是完成的简单网页的get请求抓取。如果想给链接传递一些参数?首先看一下urlopen()函数的API:
urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)
除了第一个参数传递url外,还可以传递其他内容,比如data(附加数据)、timeout(超时时间)等。
- data参数
data参数是可选的。如果要添加参数,需要用bytes()方法将参数转化为字节流编码格式的内容,即bytes类型。另外如果添加了这个参数,它的请求方式就从get方式变成了post请求:
import urllib.request
import urllib.parse
data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
response = urllib.request.urlopen('https://httpbin.org/post',data= data)
print(response.read().decode('utf-8'))
我们传递了一个参数word,值是hello。它需要被转码为bytes(字节流)类型使用bytes()方法,该方法的第一个参数需要是str(字符串)类型,需要用urllib.parse模块里的urlencoede()方法来实现将字典转化成字符串;第二个参数指定编码格式,这里指定utf-8,请求站点是httpbin.org,它可以提供http请求测试。本次请求为http://httpbin.org/post,这个链接用来测试post请求,它可以输出请求的一些信息,其中包含我们传递的data参数。
运行结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"word": "hello"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "10",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.7",
"X-Amzn-Trace-Id": "Root=1-5f94e513-71d17ff04a1ec40f05694eb4"
},
"json": null,
"origin": "58.199.177.47",
"url": "https://httpbin.org/post"
}
记得代码最后一行read()后面加解码decode(),不然结果会是b‘字母开头的bytes类型数据:
b'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "word": "hello"\n }, \n "headers": {\n "Accept-Encoding": "identity", \n "Content-Length": "10", \n "Content-Type": "application/x-www-form-urlencoded", \n "Host": "httpbin.org", \n "User-Agent": "Python-urllib/3.7", \n "X-Amzn-Trace-Id": "Root=1-5f94e726-74e8522a57671f7b16213ba3"\n }, \n "json": null, \n "origin": "58.199.177.47", \n "url": "https://httpbin.org/post"\n}\n'
- timeout参数
timeout参数用于设置时间超时,单位为秒s,超出这个时间没有响应就会抛出异常。如果不指定该参数就会使用全局默认时间。它支持http、https、ftp请求。
import urllib.request
import urllib.parse
response = urllib.request.urlopen('https://httpbin.org/get',timeout=0.1)
print(response.read())
超时抛出异常,该异常属于urllib.error模块,可以通过设置这个超时时间来控制一个网页如果长时间没响应就跳过它的抓取,可以利用try except语句来实现:
import urllib.request
import urllib.error
import socket
try:
response = urllib.request.urlopen('https://httpbin.org/get',timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason,socket.timeout):
print('TIME OUT!')
结果:
- 其他参数
context参数必须是ssl.SSLContext类型,用来指定SSL设置;
cafile和capath分别指定CA证书和它的路径,这个在请求https链接时会有用。
cadefault参数现在启用了,默认False