第二节--Urllib数据抓取

第二节–Urllib数据抓取

一.Urllib简介

Urllib是python自带的标准库,无须安装,直接引用即可。Urllib通常用于爬虫开发,API(应用程序编程接口)数据获取和测试。在python2和python3中,Urllib在不同版本中的语法有明显的改变

python2分为UrllibUrllib2Urllib2可以接收一个Request对象,并对此来设置一个URL的Headers,但是Urllib只接收一个URL,意味着不能伪装用户代理字符串等。Urllib模块可以提供进行Urlencode的方法,该方法用于GET查询字符串的生成,Urllib2不具有这样的功能。这也是UrllibUrllib2经常在一起使用的原因

在python3中,Urllib模块是一堆可以处理URL的组件集合,就是将UrllibUrllib2合并在一起使用,并且命名为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上的特殊符号还原
posted @ 2019-02-16 12:19  LQ6H  阅读(571)  评论(0编辑  收藏  举报