第二节–Urllib数据抓取
一.Urllib简介
Urllib
是python自带的标准库,无须安装,直接引用即可。Urllib
通常用于爬虫开发,API(应用程序编程接口)数据获取和测试。在python2和python3中,Urllib
在不同版本中的语法有明显的改变
python2分为Urllib
和Urllib2
,Urllib2
可以接收一个Request对象,并对此来设置一个URL的Headers,但是Urllib
只接收一个URL,意味着不能伪装用户代理字符串等。Urllib
模块可以提供进行Urlencode的方法,该方法用于GET查询字符串的生成,Urllib2
不具有这样的功能。这也是Urllib
与Urllib2
经常在一起使用的原因
在python3中,Urllib
模块是一堆可以处理URL的组件集合,就是将Urllib
和Urllib2
合并在一起使用,并且命名为Urllib
在python3中,Urllib
是一个收集几个模块来使用URL的软件包,大致具备以下功能:
- urllib.request:用于打开和读取URL
- urllib.error:包含提出的例外urllib.request
- urllib.parse:用于解析URL
- urllib.robotparser:用于解析robots.txt文件
二.发送请求
urllib.request.urlopen
的语法如下:
urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)
功能说明:Urllib
是用于访问URL(请求链接)的唯一方法
[参数说明]
url
:需要访问的网站的URL地址。url格式必须完整,如https://movie.douban.com/为完整的url,若url为movie.douban.com/,则程序运行时会提示无法识别url的错误data
:默认值为None,Urllib判断参数data是否为None从而区分请求方式。若参数data为None,则代表请求方式为Get;反之请求方式为Post,发送Post请求。参数data以字典形式存储数据,并将参数data由字典类型转换成字节类型才能完成Post请求timeout
:超时设置,指定阻塞操作(请求时间)的超时(如果未指定,就使用全局默认超时设置)cafile,capath,cadefault
:使用参数指定一组HTTPS请求的可信CA证书。cafile
应指向包含一组CA证书的单个文件;capath
应指向证书文件的目录;cadefault
通常使用默认值即可context
:描述各种SSL选项的实例
当对网站发送请求时,网站会返回相应的响应内容。urlopen
对象提供获取网站响应内容的方法函数,分别介绍如下:
read(),readline(),readlines(),fileno()和close()
:对HTTPResponse类型数据操作info()
:返回HTTPMessage对象,表示远程服务器返回的头信息getcode()
:返回HTTP状态码geturl()
:返回请求的URL
下面的例子用于实现Urllib
模块对网站发送请求并将响应内容写入文本文档,代码如下:
# 导入urllib
import urllib.request
# 打开url
response=urllib.request.urlopen("https://movie.douban.com/",None,2)
# 读取返回的内容
html=response.read().decode("utf8")
# 写入txt
f=open("html.txt","w",encoding="utf8")
f.write(html)
f.close()
首先导入urllib.request
模块,然后通过urlopen
访问一个URL,请求方式是GET,所以参数设置为None;最后的参数用于设置超时时间,设置为3秒,如果超过2秒,网站还没返回响应数据,就会提示请求失败的错误信息
当得到服务器的响应后,通过response.read()获取其响应内容。read()
方法返回的是一个bytes类型的数据,需要通过decode()
来转换成str类型。最后将数据写入文本文档中,encoding
用于设置文本文档的编码格式,数据编码必须与文本文档编码一致,否则会出现乱码
三.复杂的请求
urllib.request.Request
的语法如下:
urllib.request.Request(url,data=None,headers={},method=None)
功能说明:声明一个request对象,该对象可自定义header(请求头)等请求信息
[参数解释]:
url
:完整的url格式,与urllib.request.urlopen
的参数url一致data
:请求参数,与urllib.request.urlopen
的参数data一致headers
:设置request请求头信息method
:设定请求方式,主要是POST和GET方式
一个完整的HTTP请求必须要有请求头信息。而urllib.request.Request
的作用是设置HTTP的请求头信息。使urllib.request.Request
设置请求头,代码如下:
# 导入urllib
import urllib.request
url="https://movie.douban.com/"
# 自定义请求头
headers={
'User-Agent':'Mozilla/5.0(Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
'Referer':'https://movie.douban.com/',
'Connnection':'keep-alive'
}
# 设置request的请求头
req=urllib.request.Request(url,headers=headers)
# 使用urlopen打开req
html=urllib.request.urlopen(req).read().decode('utf-8')
# 写入文件
f=open('html.txt','w',encoding='utf8')
f.write(html)
f.close()
四.代理IP
代理IP的原理:以本机先访问代理IP,再通过代理IP地址访问互联网,这样网站(服务器)接收到的访问IP就是代理IP地址
Urllib
提供了urllib.request.ProxyHandler()
方法可动态设置代理IP池,代理IP主要以字典格式写入方法。完成代理IP设置后,将设置好的代理IP写入urllib.request.bulid_opener()
方法,生成对象opener
,然后通过opener的open()
方法向网站(服务器)发送请求
使用代理IP访问网站,代码如下:
import urllib.request
url='https://movie.douban.com/'
# 设置代理IP
proxy_handler=urllib.request.ProxyHandler(
{
'http':'218.56.132.157:8080',
'https':'183.30.197.29:9797'
}
)
# 必须使用bulid_opener()函数来创建带有代理IP功能的opener对象
opener=urllib.request.build_opener(proxy_handler)
response=opener.open(url)
html=response.read().decode("utf-8")
f=open('html.txt','w',encoding='utf8')
f.write(html)
f.close()
注意,由于使用代理IP,因此连接IP的时候有可能出现超时而导致报错,遇到这种情况只要更换其他代理IP地址或者再次访问即可。以下是常见的报错信息:
ConnectionResetError
:[WinError 10054]远程主机强迫关闭了一个现有的连接urllib.error.URLError
:urlopen error Remote end closed connection without response(结束没有响应的远程连接)urllib.error.URLError
:urlopen error [WinError 10054]远程主机强迫关闭了一个现有的连接TimeoutError
:[WinError 10060]由于连接方在一段时间后没有正确答复或连接的主机没有反应,因此连接尝试失败urllib.error.URLError
:urlopen error[WinError 10061]由于目标计算机拒绝访问,因此无法连接
五.使用Cookies
Cookies
主要用于获取用户登录信息,比如通过提交数据实现用户登录之后,会产生带有登录状态的Cookies
,这时可以将Cookies
保存在本地文件中,下次程序运行的时候,可以直接读取Cookies
文件来实现用户登录
Urllib
提供HTTPCookieProcessor()
对Cookies
操作。但Cookies
的读写是由MozillaCookieJar()
完成的。下面的例子实现Cookies
写入文件,代码如下:
import urllib.request
from http import cookiejar
filename='cookie.txt'
# MozillaCookiesJar保存cookie
cookie=cookiejar.MozillaCookieJar(filename)
# HTTPCookieProcessor创建cookie处理器
handler=urllib.request.HTTPCookieProcessor(cookie)
# 创建自定义opener
opener=urllib.request.build_opener(handler)
# open方法打开网页
response=opener.open('https://movie.douban.com')
# 保存cookie文件
cookie.save()
代码中的cookiejar
是自动处理HTTP Cookie的类,MozillaCookieJar()
用于将Cookies
内容写入文件。程序运行时先创建MozillaCookieJar()
对象,然后将对象直接传入函数HTTPCookieProcessor()
,生成opener
对象;最后使用opener
对象访问URL,访问过程所生成的Cookies
就直接写入已创建的文本文档中
接着再看如何读取Cookies
,代码如下:
import urllib.request
from http import cookiejar
filename='cookie.txt'
# 创建MozillaCookieJar对象
cookie=cookiejar.MozillaCookieJar()
# 读取cookie内容到变量
cookie.load(filename)
# HTTPCookieProcessor创建cookie处理器
handler=urllib.request.HTTPCookieProcessor(cookie)
# 创建opener
opener=urllib.request.build_opener(handler)
# opener打开网页
response=opener.open('https://movie.douban.com')
# 输出结果
print(cookie)
读取和写入的方法很相似,主要区别在于:两者对MozillaCookieJar()
对象的操作不同,导致实现功能也不同
注意,为了方便测试,上述代码中使用的cookie.save()
和cookie.load(filename)
将Cookies
内容显示在文本文档中。在实际开发中,为了提高安全性,可以在保存和读取Cookies
时设置参数,使Cookies
信息隐藏在文件中。方法如下
cookie.save(ignore_discard=True,ignore_expires=True)
cookie.load(filename,ignore_discard=True,ignore_expires=True)
六.证书验证
当遇到一些特殊的网站时,在浏览器上会显示连接不是私密连接而导致无法浏览该网页
补充:
CA证书
也叫SSL证书
,是数字证书的一种,类似于驾驶证护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书
SSL证书
就是遵守SSL协议,由受信任的数字证书机构颁发CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能
SSL证书
在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure Socket Layer,SSL),安全协议是由Netscape Communication公司设计开发的
遇到这类验证证书的网站,最简单而暴力的方法是直接关闭证书验证,可以在代码中引入SSL模块,设置关闭证书验证即可。代码如下:
import urllib.request
import ssl
# 关闭证书验证
ssl._create_default_https_context=ssl._create_unverified_context
url='https://kyfw.12306.cn/otn/leftTicket/init'
response=urllib.request.urlopen(url)
# 输出状态码
print(response.getcode())
七.数据处理
我们知道urllib.request.urlopen()
方法是不区分请求方式的,识别请求方式主要通过参数data是否为None。如果向服务器发送Post请求,那么参数data需要使用rullib.parse
对参数内容进行处理
Urllib
在请求访问服务器的时候,如果发生数据传递,就需要对内容进行编码处理,将包含str或bytes对象的两个元素元组序列转换为百分比编码的ASCII文本字符串。如果字符串要用作Post,那么它应该被编码为字节,否则会导致TypeError错误
Urllib
发送Post请求的方法如下:
import urllib.request
import urllib.parse
url='https://movie.douban.com'
data={
'value':'true'
}
# 数据处理
data=urllib.parse.urlencode(data).encode('utf-8')
req=urllib.request.urlopen(url,data=data)
代码中urllib.parse.urlencode(data)
将数据转换成字节的数据类型,而encode(utf-8)
设置字节的编码格式。urlencode()
的作用只是对请求参数做数据格式转换处理
除此之外,Urllib
还提供quote()
和unquote()
对URL编码处理,使用方法如下
import urllib.parse
url='%2523%25E7%25BC%2596%25E7%25A8%258B%2523'
# 第一次编码
first=urllib.parse.unquote(url)
print(first)
second=urllib.parse.unquote(first)
print(second)
八.本章小结
在python2和python3中,Urllib
语法有明显的改变。其常用的语法有以下几种:
urllib.request.urlopen
:urllib最基本的使用功能,用于访问URL(请求链接)的唯一方法urllib.request.Request
:声明request对象,该对象可自定义请求头(header),请求方式等信息urllib.request.ProxyHandler
:动态设置代理IP池,可加载请求对象urllib.request.HTTPCookieProcessor
:设置Cookies对象,可加载请求对象urllib.request.build_opener()
:创建请求对象,用于代理IP和Cookies对象加载urllib.parse.urlencode(data).encode('utf-8')
:请求数据格式转换urllib.parse.quote(url)
:URL编码处理,主要对URL上的中文等特殊符号编码处理rullib.parse.unquote(url)
:URL解码处理,将URL上的特殊符号还原