我又来装逼了!上次教大家写了一个下载www.mzitu.com全站图片的小爬虫练手、不知道大家消化得怎么样? 大家在使用的时候会发现,跑着跑着 就断掉了!报错了啊!丢失连接之类的。幸幸苦苦的抓了半天又得从头来,心累啊! 这就是网站的反爬虫在起作用了,一个 IP 访问次数过于频繁就先将这个 IP 加入黑名单,过一会儿再放出来。虽然不影响正常使用但是对于爬虫来说很致命啊!因为爬虫会报错退出啊!然后我们又得重来,那么多妹子得重来多少次啊!(而且小爬虫不会识别哪些是爬取过的页面,哪些是没爬去的内容,会从头再来啊!很伤人啊!关于这一块儿我下一篇博文来教大家怎么办,这一篇我们还是先集中精力应付反爬虫吧! 关于反爬虫的定义:建议大家去看看这个 blog: 点我 一般来说我们会遇到网站反爬虫策略下面几点:
- 限制 IP 访问频率,超过频率就断开连接。(这种方法解决办法就是,降低爬虫的速度在每个请求前面加上 time.sleep;或者不停的更换代理 IP,这样就绕过反爬虫机制啦!)
- 后台对访问进行统计,如果单个 userAgent 访问超过阈值,予以封锁。(效果出奇的棒!不过误伤也超级大,一般站点不会使用,不过我们也考虑进去
- 还有针对于 cookies 的 (这个解决办法更简单,一般网站不会用)
我们今天就来针对 1、2 两点来写个下载模块、别害怕真的很简单。 首先,这次我们需要用到 Python 中的 re 模块来提取内容,很简单的用法,但是也需要各位了解一下:点我查看正则表达式基本教程 首先照常我们需要下面这些模块: requests re(Python 的正则表达式模块) random(一个随机选择的模块) 都是上一篇文章装过的哦!re 和 random 是 Python 自带的模块,不需要安装ヾ§  ̄ ▽)ゞ 2333333 首先按照惯例我们导入模块:
1 |
import requests |
我们的思路是先找一个发布代理 IP 的网站(百度一下很多的!)从这个网站爬取出代理 IP 用来访问网页;当本地 IP 失效时,开始使用代理 IP,代理 IP 失败六次后取消代理 IP。下面我们开整ヽ(●-`Д´-)ノ 首先我们写一个基本的请求网页并返回 response 的函数:
1 |
import requests |
哈哈 简单吧! 这只是基本的,上面说过啦,很多网站都都会拒绝非浏览器的请求的、怎么区分的呢?就是你发起的请求是否包含正常的 User-Agent 这玩意儿长啥样儿?就下面这样(如果不一样 请按一下 F5) requests的请求的 User-Agent 大概是这样 python-requests/2.3.0 CPython/2.6.6 Windows/7 这个不是正常的 User-Agent、所以我们得自己造一个来欺骗服务器(requests 又一个 headers 参数能帮助我们伪装成浏览器哦!不知道的小哥儿 一定是没有看官方文档!这样很不好诶!o(一︿一+)o),让他以为我们是真的浏览器。 上面讲过有的网站会限制相同的 User-Agent 的访问频率,那我们就给他随机来一个 User-Agent 好了!去百度一下 User-Agent,我找到了下面这些:
1 |
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", |
下面我们来改改上面的代码成这样:
1 |
import requests |
各位可以自己实例化测试一下,headers 会不会变哦 ε=ε=ε=(~ ̄ ▽  ̄)~ 好啦下面我们继续还有一个点没有处理:那就是限制 IP 频率的反爬虫。 首先是需要获取代理 IP 的网站,我找到了这个站点 http://haoip.cc/tiqu.htm(这儿本来我是准备教大家自己维护一个 IP 代理池的,不过有点麻烦啊!还好发现这个代理站,还是这么好心的站长。我就可以光明正大的偷懒啦!ヾ(≧O≦)〃嗷~) 我们先把这写 IP 爬取下来吧!本来想让大家自己写,不过有用到正则表达式的,虽然简单,不过有些小哥儿(妹儿)怕是不会使。我也写出来啦.
1 |
iplist = [] ##初始化一个list用来存放我们获取到的IP |
我们来打印一下看看 下面[———————]中的内容就我们添加进 iplist 这个初始化的 list 中的内容哦! 完美!!好啦现在我们把这段代码加到之前写的代码里面去;并判断是否使用了代理:
1 |
import requests |
需要测试的小哥儿(妹儿),可以自行测试哦。 下面我开始判断什么时候需要 !需要使用代理,而且还得规定一下多少次切换成代理爬取,多少次取消代理啊!我们改改代码,成下面这样:
1 |
import requests |
上面代码添加了一个 timeout (防止超时)、一个 num_retries=6(限制次数,6 次过后使用代理)。 下面我们让使用代理失败 6 次后,取消代理,直接上代码:
1 |
import requests |
收工一个较为健壮的下载模块搞定(当然一个健壮的模块还应该有其它的内容,比如判断地址是否是 robots.txt 文件禁止获取的;错误状态判断是否是服务器出错,限制爬虫深度防止掉入爬虫陷进之类的····) 不过我怕太多大家消化不了,而且我们一般遇到的网站基本不会碰到爬虫陷阱(有也不怕啊,反正规模不大,自己也就注意到了。) 下面我们来把这个下载模块使用到我们上一篇博文的爬出红里面去! 用法很简单!ヾ(´▽‘)ノ将这个 py 文件放在和上一篇博文爬虫相同的文件夹里面;并新建一个init.py 的文件。像这样: 在爬虫里面导入下载模块即可,class 继承一下下载模块;然后替换掉上一篇爬虫里面的全部 requests.get,为 download.get 即可!还必须加上 timeout 参数哦!废话不多说直接上代码:
1 |
from bs4 import BeautifulSoup |
好了!搞完收工!大家可以看一下和上一次我们写的爬虫有哪些变化就知道我们做了什么啦! 2016/11/4 更新:今天做教程的时候发现我忽略了一个问题,上面的写法,属于子类继承父类,这种写法 子类没法用init;所以我改了一下写法,(其余都没变,不用担心。)直接贴代码了: 首先是下载模块(Download.py):
1 |
import requests |
这个模块就多了 request = download() 第二个(def mzitu.py):
1 |
from bs4 import BeautifulSoup |
改动的地方我都有明确标注哦!仔细看看有什么不同吧。