python爬虫系列(三)我的第一个爬虫
一、前言:
- 我们之前学习了一些爬虫相关的知识点,还未涉及到爬虫的编写。
- 有些小伙伴可能知道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。
-
感谢您的观看。