python爬虫系列(三)我的第一个爬虫

  发布日期:   2017-09-10
  最新修改:   2020-09-20
  阅读次数:   61 次

一、前言:

  • 我们之前学习了一些爬虫相关的知识点,还未涉及到爬虫的编写。

  • 有些小伙伴可能知道scrapy这个爬虫框架,这是一个功能强大的爬虫架构,其中我学习过的一个Webmagic的设计思想也参考了该框架。

  • 一开始我们肯定写不出这样的爬虫框架,但是我们的目标是从0开始。

  • 参考其思想,主要实现四个组件:

    download:负责下载网络资源 spider:接收下载好的数据,完成数据解析、获取下一个需要请求的url等。 pipeline:接收解析后的数据,完成数据的存储等操作 Scheduler:负责调度我们的爬虫

  • 本章我们将从0到1先写一个简单的爬虫。

二、urllib的使用

  • 由于我使用的是python3,3.x的版本urllib与urllib2已经合并为一个urllib库

  • urllib使用详解:

    1、urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) 描述:使用该方法来发起一个网络请求 参数解析:url 可以为一个字符串或者一个Request对象,data为发送给服务端的数据,timeout为设置一个默认的超时值,如果不设置则使用一个默认的全局的。cafile和capath与Https和CA证书有关。content则与SSL相关

  • 目前的参数我们只需要关系url即可,你可以直接传递一个请求的连接地址直接发起请求,也可以通过构造一个Request对象来发起请求,强烈建议采用后者,因为后面我们肯定要对设置请求代理之类的参数,而且先构造一个请求对象,然后发起网络请求也比较符合我们的编程习惯。

  • 所以后面的编码默认通过构造Request的方式来发起网络请求。

  • OK,既然决定使用构造Request的形式来进行网络请求,所谓磨刀不误砍柴工,我们先来熟悉一下Request这个类的结构:

Request类介绍:

  • 构造函数:urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

    1、url:字符串,应该是一个可用的url请求地址 2、data:必须是一个对象,其作为发送给服务端的数据,如果没有则为None,当前的http请求支持byte对象,文件对象和可迭代对象,如果不在http的头部字段中设置Content-Length也不设置 Transfer-Encoding,HTTPHandler将会根据data的数据类型来设置。 如果请求方式为post,data类型应该作为一种以标准的application/x-www-form-urlencoded格式的缓存数据。 3、headers:字典类型,设置http请求的头部信息,通常的代理,浏览器参数等就是通过headers来设置,也可通过add_heard()设置,设置形式为key:value的形式 4、method:请求的方法,常用的有get、post,当然还有delete等等。 其余的不常用,这里就不多介绍了

  • OK,介绍完之后我们来看一个简单的访问百度的代码:

      from urllib import request, error, response
      def download(url):
          print('download url is %s' % url);
          html = None;
          try:
              rq = request.Request(url=url);
              rp = request.urlopen(rq);
              print(dir(rp))
              print('download over url is: %s'%rp.geturl())
              # print('response code is %d' % r.code);
              html = rp.read();
          except error.URLError as e:
              print('download  error :%s' % e.reason);
              html = None;
    
          return html;
    
      if __name__ == '__main__':
          print(download('http://www.baidu.com'))
  • 由于结果输出来一个百度的页面代码,这里就不贴出来了,感兴趣的小伙伴可以尝试运行一下。

  • 我们构建好request后,调用urlopen即发起了一个请求,会返回一个响应.我们可以通过r.read()方法读取相应的数据。当然,返回的对象还有很多其它有用的属性,如code存储了响应码,200表示请求成功,如果遇到301、302这些,我们还需要进行重定向请求。遇到500这种一般需要进行重新请求。

  • OK,下面我们就来加一个帶重启次数的download版本:

      from urllib import request, error, response
      def download(url, num_retries=2):
          print('download url is %s' % url);
          html = None;
          try:
              rq = request.Request(url=url);
              rp = request.urlopen(rq);
              print(dir(rp))
              print('download over url is: %s'%rp.geturl())
              # print('response code is %d' % r.code);
        html = rp.read();
          except error.URLError as e:
              print('download  error :%s' % e.reason);
              html = None;
              if num_retries > 0:
                  if hasattr(e,'code') and 500 <= e.code < 600:
                      return download(url, num_retries - 1);
                  pass;
    
          return html;
    
      if __name__ == '__main__':
          print(download('http://www.baidu.com',2))
  • 如此我们便通过判断状态码实现了下载失败重新下载的功能。

  • Ok,我们将采用小步快跑的方式,每章控制一定的篇幅,这样学习起来个人感觉应该会好一些。

  • 当然,下伙伴没有更好的学习方式也可以给我留言哦。

  • 本次我们就先学到这里,下篇我们将学习代理的设置,以及从请求的网络中解析出下一请求的url。

  • 感谢您的观看。


   转载规则

《python爬虫系列(三)我的第一个爬虫字》GajAngels 采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。