zoukankan      html  css  js  c++  java
  • 第二节--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上的特殊符号还原
  • 相关阅读:
    年轻人的第一个 Spring Boot 应用,太爽了!
    面试问我 Java 逃逸分析,瞬间被秒杀了。。
    Spring Boot 配置文件 bootstrap vs application 到底有什么区别?
    坑爹的 Java 可变参数,把我整得够惨。。
    6月来了,Java还是第一!
    Eclipse 最常用的 10 组快捷键,个个牛逼!
    Spring Cloud Eureka 自我保护机制实战分析
    今天是 Java 诞生日,Java 24 岁了!
    厉害了,Dubbo 正式毕业!
    Spring Boot 2.1.5 正式发布,1.5.x 即将结束使命!
  • 原文地址:https://www.cnblogs.com/LQ6H/p/10387316.html
Copyright © 2011-2022 走看看