• 第二节--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上的特殊符号还原
  • 相关阅读:
    $(document).ready(function(){}) 与 window.onload = function(){} 区别
    [如何在Mac下使用gulp] 1.创建项目及安装gulp
    Mac 执行 gulp 报错 bash: gulp: command not found
    css 字体单位之间的区分以及字体响应式实现
    [nodejs]在mac环境下如何将node更新至最新?
    [angular 1.x] 使用select 实现下拉列表 ngoptions 与 ngrepeat的取舍
    事件冒泡、事件捕获、事件委托初探
    Android 随机铃声管理器
    git 强制恢复到某一版本
    混乱中生存
  • 原文地址:https://www.cnblogs.com/LQ6H/p/10387316.html
Copyright © 2020-2023  润新知