zoukankan      html  css  js  c++  java
  • python3网络爬虫系统学习:第一讲 基本库urllib

    在python3中爬虫常用基本库为urllib以及requests

    本文主要描述urllib的相关内容

    urllib包含四个模块:requests——模拟发送请求

             error——异常处理模块

             parse——关于URL处理方法的工具模块

             robotparser——通过识别网站robot.txt判断网站的可爬取内容

    一、发送请求

      urllib库发送请求主要使用request模块中的两个内容:urlopen()方法以及Requests类,其中Requests类是结合urlopen()方法来使用的。

      首先,看一下urlopen()方法的API:

    urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,context=None)

        参数详细介绍:url——必填内容

               data——POST方式请求时,需要传递该参数。传递该参数时需要注意要将参数转化为字节流编码格式(bytes类型)

               timeout——设置超时时间,当超出该时间时,抛出超时异常。使用该参数有两种方式:timeout=5或者timeout=(5,30),前者表示connect+read时间为5s,后者表示connect时间为5s+read时间30s

               context——参数值必须是ssl.SSLContext类型

               cafile,capath——指定CA整数以及路径

        注:bytes()方法的使用——bytes(string,code)      第一个参数用来指定字符串,第二个参数用来指定编码格式

          将dict转化为string的方法     urllib.parse.urlencode(dict)

      实例应用:

     1 import urllib.parse
     2 import urllib.request
     3 
     4 url = 'http://httpbin.org/post'
     5 data = bytes(urllib.parse.urlencode({'name':'value'}), encoding='utf8')
     6 timeout = (3, 10)
     7 
     8 response = urllib.request.urlopen(url,data=data,timeout=timeout)
     9 
    10 # 输出response的类型
    11 print(type(response))
    12 # 输出网页内容
    13 print(response.read().decode('utf8'))

      通过type(response),我们发现urlopen()是返回一个HTTPResponse类型对象,该对象主要包括以下方法和属性

        read()——返回网页内容

        getheaders()——返回响应头信息

        getheader(name)——返回属性名为name的响应头中name对应的属性值

        msg、version、status(状态码)、reason、debuglevel、closed

      接下来,看一下Request类构建方法,该方法主要是解决urlopen()方法不容易解决的请求构建问题,例如添加Headers等信息

      Request类的API:

    urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)

      url——必传参数

      data——bytes()类型

      headers——字典,请求头信息,常用User-Agent信息来伪装请求头

      origin_req_host——请求方的host方法或者IP地址

      unverifiable——指请求是否是无法认证的,当我们没有抓取权限时,该参数的值为True,默认为False

      method——参数值为字符串,指定请求使用的方法,比如GET、POST等

      实例应用:

     1 from urllib import request,parse
     2 
     3 url = 'http://httpbin.org/post'
     4 headers = {
     5     'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; WIndows NT)'
     6     'Host': 'httpbin.org'
     7 }
     8 dict = {
     9     'name': 'Germey'
    10 }
    11 data = bytes(parse.urlcode(dict), encoding='utf8')
    12 
    13 req = request.Request(url=url,data=data,headers=headers,method='POST')
    14 response = request.urlopen(req)

      此外,对于一些更高级的操作(Cookies处理、代理设置等)需要借助Handler工具

      在urllib.request模块中BaseHandler类提供了几种最基本的方法:default_open()、protocol_request()等,其他各种Handler子类都会继承该类。

      HTTPDefaultErrorHandler:处理HTTP响应错误,错误抛出HTTPError类型异常

      HTTPRedirectHandler:处理重定向

      HTTPCookieProcessor:用于处理Cookies

      ProxyHandler:用于设置代理,默认代理为空

      HTTPPasswordMgr:用于管理密码,维护了用户名和密码的表

      HTTPBasicAuthHandler:用于管理认证,打开一个链接时需要认证时则使用该子类

      使用以上子类时,需要借助OpenerDirector类,可以称为Opener。上面讲述的urlopen()方法实际上就是urllib为我们提供的Opener,当我们使用上述子类的操作时,就需要借助Handler来构建Opener

      实例应用:

    # 认证
    from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
    from urllib.error import URLError
    
    username = 'username'
    password = 'password'
    url = 'http://localhost:5000/'
    
    # 构建密码管理
    p = HTTPPasswordMgrWithDefaultRealm()
    p.add_password(None, url, username, paaword)
    # 构建认证管理
    auth_handler = HTTPBasicAuthHandler(p)
    opener = build_opener(auth_handler)
    
    try:
        response = opener.open(url)
        html = response.read(),decode('utf8')
        print(html)
    except URLError as e:
        print(e.reason)
    
    
    # 代理
    from urllib.request import ProxyHandler, build_opener
    
    proxy_handler = ProxyHandler({
        'http': 'http://127.0.0.1:9743'
        'https': 'https://127.0.0.1:9743'
    })
    opener = builder_opener(proxy_handler)
    
    
    # Cookies获取
    import http.cookiejar, urllib.request
    cookie = http.cookiejar.CookieJar()
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open(url)
    for item in cookie:
        print(item.name+'='+item.value)
    # Cookie输出到文件
    filename = 'cookies.txt'
    cookie = http.cookiejar.MozillaCookieJar(filename)   #保存成Mozilla型浏览器的Cookie格式
    cookie = http.cookiejar.LWPCookieJar(filename)   #保存为LWP格式
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open(url)
    cookie.save(ignore_discard=True, ignore_expires=True)
    # 从文件中读取cookie
    cookie = http.cookiejar.LWPCookieJar()
    cookie.load(filename, ignore_discard=True, ignore_expires=True)
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open(url)

    二、异常处理

      通过合理的捕获异常可以做出更准确的异常判断,使得程序更加稳健。 

      常用的异常处理类有URLError类和HTTPError类,其中HTTPError类是URLError类的子类。有request模块产生的异常都可以通过捕获URLError类来实现,它有一个属性reason,返回错误的原因。HTTPError专门用来处理HTTP请求错误,它有三个属性:code、reason以及headers,code返回HTTP状态码,reason返回错误原因,headers返回请起头。

      reason属性返回可能是字符串,也可能是对象。

      在具体使用时,我们可以先选择捕获子类错误,再选择捕获父类错误。

      实例应用:

     1 from urllib import request,error
     2 '''
     3 上述引用就相当于
     4 import urllib.request
     5 import urllib.error
     6 '''
     7 
     8 url = 'http://www.baidu.com'
     9 try:
    10     response = request.urlopen(url)
    11 except error.HTTPError as e:
    12     print(e.reason, e.code, e.headers, sep='
    ')
    13 except error.URLError as e:
    14     print(e.reason)
    15 else:
    16     print('Reuqest Successfully')

    三、url链接解析

      urllib库里面提供的parse模块,它定义了处理URL标准接口,下面我们介绍一下该模块的常用方法。

      urlparse()——实现URL识别和分段,该方法会将url拆分成6个部分。分别是:scheme(协议)、netloc(域名)、path(访问路径)、params(参数)、query(参数)以及fragment(锚点),这六个元素构成的url链接格式为

              scheme://netloc/path;params?query#fragment

            urlparse()的api用法如下:

    urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

      参数详解:

        urlstring:必填项,待解析的URL

        scheme:选填项,默认的协议,当链接没有协议信息是,会使用该默认协议

        allow_fragments:选填项,该参数为是否fragment。当fragment=False时,原有的fragement部分就会被解析为 path、params或者query的一部分,而fragment部分会变为空

      此外,urlparse()的返回值是一个元组,我们可以根据索引顺序来获取我们需要的内容,也可以根据属性名来获取

      实例应用:

    1 from urllib.parse import urlparse
    2 
    3 url = 'http://www.baidu.com/index.html#comment'
    4 result = urlparse(url,allow_fragments=False)
    5 
    6 print(result.scheme, result[0], sep='
    ')

      接下来,我们看一下有关链接解析的其他方法:

      urlunparse()——根据参数的到链接,相当于urlparse()方法的逆转。值得注意的是,此方法的可迭代对象参数的长度必须为6

    from urllib.parse import urlunparse
    
    data = ['http',www.baidu.com','index.html','user','a=6','comment']
    print(urlunparse(data))

      urlsplit()——与urlparse()类似,也是用来分解url的。不同的是,该方法的返回值长度仅为5,其中,不再单独解析params,而是归到path里面

      urlunsplit()——与urlunparse()类似,是urlsplit()的逆转,参数长度为5

      urljoin()——生成链接的另外一种方法,API如下:

    urllib.parse.urljoin(base_url,url)

      base_url:基础链接。该方法会解析base_url的scheme、netlocal以及path

      url:待处理的新链接。其形式多样化,可包含url的6个部分的全部内容,也可以是仅包含其中某几个连续的内容。

      当新链接内容缺失时,该方法会根据base_url的解析信息对其缺失部分进行补充,并返回补充后的新链接或不需补充的待处理链接

      应用实例:

    from urllib.parse import urljoin
    urljoin('http://baidu.com/index.html','FAQ.html')

      值得注意的是,即使base_url中包含params、query以及fragment部分,也是不起任何作用的

      urlencode()——序列化GET请求参数。所谓序列化就是将字典转化为参数所需的字符串

    1 from urllib.parse import urlencode
    2 
    3 params = {
    4     'name': 'germey'
    5     'age': 22       
    6 }
    7 base_url = 'http://www.baidu.com'
    8 url = base_url+urlencode(params)
    9 print(url)

      parse_qs()——反序列化

      parse_qsl()——将参数化为元组组成的列表

    1 from urllib.parse import parse_qs,parse_qsl
    2  
    3 query = 'name=germey&age=22'
    4 print(parse_qs(query))
    5 print(parse_qsl(query))

      quote()——将中文字符转化为URL编码

      unquote()——将URL解码

    1 from urllib.parse import quote
    2 
    3 keyword = '壁纸'
    4 url = 'http://www.baidu.com/s?wd=' + quote(keyword)
    5 print(url)
    6 print(unquote(url))

      

    四、Robots协议

      经过这么久的学习,终于到了urllib库的最后一个模块robotparser模块,通过该模块我们可以实现网站Robots协议的分析

      首先,我们了解一下什么是Robots协议

      Robots协议也称为爬虫协议,全名是网络爬虫排除标准。用途是来告诉爬虫和搜索引擎哪些页面可以抓取,而哪些不可以。通常是一个叫做robots.txt的文本文件。通常放在网站的根目录下。当搜索爬虫访问站点时,会首先检查是否存在该文件,若存在,再根据定义的爬取范围来爬取信息。

      robots.txt范例

    User-agent: *
    Disallow: /
    Allow: /public/

       其中,User-agent描述了搜索爬虫的名称,其值也可以是BaiduSpider、Googlebot等;Disallow指定了不允许抓取的目录,‘/’表示不允许抓取所有页面;Allow用来排除某些例外,通常和Disallow结合使用,/public/表示可以抓取public目录,相当于白名单的作用

      了解Robots协议后,我们可以通过robotparser模块来解析robots.txt。robotparser模块API如下:

    urllib.robotparser.RobotFileParser(url='')

       我们可以在使用该模块时,直接传入url,也可以通过set_url方法来设置。我们看一下该模块的常用方法:

      set_url()——设置robots.txt文件位置链接

      read()——读取robots.txt并进行分析,值得注意的是,我们一定要执行该方法以完成对文件的读取,虽然该方法并没有返回值

      parse()——解析robots.txt文件,传入参数是robots.txt某些行的内容

      can_fetch()——该方法传入两个参数,第一个是User-agent,第二个是要抓取的URL。返回布尔型结果,表示User-agent是否可以抓取该页面

      mtime()——上次抓取和分析robots.txt的时间,目的在于定期检查robots.txt文件

      modtime()——将当前时间设置为上次抓取和分析时间

      实例应用:

    1 from urllib.robotparser import RobotFileParser
    2 
    3 rp = RobotFileParser()
    4 rp.set_url('http://www.jianshu.com/robots.txt')
    5 rp.read()
    6 # rp.parse(rp.read().decode('utf8').split('
    '))
    7 print(rp.can_fetch('*','http://www.jianshu.com/p/b67554025d7d'))
    8 print(rp.can_fetch('*','http://www.jianshu.com/search?q=python&page=1&type=collections'))

      小编终于写完该部分的内容了,准备去休息啦。

      在这里,小编推一下自己新建的公众号,欢迎大家积极前来探讨问题。

  • 相关阅读:
    使用MySQL Workbench建立数据库,建立新的表,向表中添加数据
    IntelliJ IDEA15开发时设置中java complier 的问题
    IntelliJ 15 unmapped spring configuration files found
    Redis 的性能
    SSH框架
    jquery插件模版
    cygwin,在win中开发linux程序
    MinGw与CyGwin
    升级到tomcat8时Artifact SpringMvcDemo:war exploded: Server is not connected. Deploy is not
    Socket连接超时(转)
  • 原文地址:https://www.cnblogs.com/jpapplication/p/10703274.html
Copyright © 2011-2022 走看看