啥话都不说了、进入正题。 首先我们更新一下scrapy版本。最新版为1.3 再说一遍Windows的小伙伴儿 pip是装不上Scrapy的。推荐使用anaconda 、不然还是老老实实用Linux吧
1 |
conda install scrapy==1.3 |
安装Scrapy-Redis
1 |
conda install scrapy-redis |
需要注意: Python 版本为 2.7,3.4 或者3.5 。个人使用3.6版本也没有问题 Redis>=2.8 Scrapy>=1.0 Redis-py>=2.1 。 3.X版本的Python 都是自带Redis-py 其余小伙伴如果没有的话、自己 pip 安装一下。 开始搞事! 开始之前我们得知道scrapy-redis的一些配置:PS 这些配置是写在Scrapy项目的settings.py中的!
1 |
|
请各位小伙伴儿自行挑选需要的配置写到项目的settings.py文件中 英语渣靠Google、看不下去的小伙伴儿看这儿:http://scrapy-redis.readthedocs.io/en/stable/readme.html 继续在我们上一篇博文中的爬虫程序修改: 首先把我们需要的redis配置文件写入settings.py中: 如果你的redis数据库按照前一片博文配置过则需要以下至少三项
1 |
SCHEDULER = "scrapy_redis.scheduler.Scheduler" |
第三项请按照你的实际情况配置。 Nice配置文件写到这儿。我们来做一些基本的反爬虫设置 最基本的一个切换UserAgent! 首先在项目文件中新建一个useragent.py用来写一堆 User-Agent(可以去网上找更多,也可以用下面这些现成的)
1 |
agents = [ |
现在我们来重写一下Scrapy的下载中间件(哇靠!!重写中间件 好高端啊!!会不会好难!!!放心!!!So Easy!!跟我做!包教包会,毕竟不会你也不能顺着网线来打我啊): 关于重写中间件的详细情况 请参考 官方文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/downloader-middleware.html#scrapy.contrib.downloadermiddleware.DownloaderMiddleware 在项目中新建一个middlewares.py的文件(如果你使用的新版本的Scrapy,在新建的时候会有这么一个文件,直接用就好了) 首先导入UserAgentMiddleware毕竟我们要重写它啊!
1 |
import json ##处理json的包 |
开写:
1 |
class UserAgentmiddleware(UserAgentMiddleware): |
第一行:定义了一个类UserAgentmiddleware继承自UserAgentMiddleware 第二行:定义了函数process_request
(request, spider)为什么定义这个函数,因为Scrapy每一个request通过中间 件都会调用这个方法。 第三行:随机选择一个User-Agent 第四行:设置request的User-Agent为我们随机的User-Agent ^_^Y(^o^)Y一个中间件写完了!哈哈 是不是So easy! 下面就需要登陆了。这次我们不用上一篇博文的FromRequest来实现登陆了。我们来使用Cookie登陆。这样的话我们需要重写Cookie中间件!分布式爬虫啊!你不能手动的给每个Spider写一个Cookie吧。而且你还不会知道这个Cookie到底有没有失效。所以我们需要维护一个Cookie池(这个cookie池用redis)。 好!来理一理思路,维护一个Cookie池最基本需要具备些什么功能呢?
- 获取Cookie
- 更新Cookie
- 删除Cookie
- 判断Cookie是否可用进行相对应的操作(比如重试)
好,我们先做前三个对Cookie进行操作。 首先我们在项目中新建一个cookies.py的文件用来写我们需要对Cookie进行的操作。 haoduofuli/haoduofuli/cookies.py: 首先日常导入我们需要的文件:
1 |
import requests |
首先我们把登陆用的账号密码 以Key:value的形式存入redis数据库。不推荐使用db0(这是Scrapy-redis默认使用的,账号密码单独使用一个db进行存储。) 就像这个样子。 解决第一个问题:获取Cookie:
1 |
import requests |
这段很好懂吧。 使用requests模块提交表单登陆获得Cookie,返回一个通过Json序列化后的Cookie(如果不序列化,存入Redis后会变成Plain Text格式的,后面取出来Cookie就没法用啦。) 第二个问题:将Cookie写入Redis数据库(分布式呀,当然得要其它其它Spider也能使用这个Cookie了)
1 |
def init_cookie(red, spidername): |
使用我们上面建立的redis链接获取redis db2中的所有Key(我们设置为账号的哦!),再从redis中获取所有的Value(我设成了密码哦!) 判断这个spider和账号的Cookie是否存在,不存在 则调用get_cookie函数传入从redis中获取到的账号密码的cookie; 保存进redis,Key为spider名字和账号密码,value为cookie。 这儿操作redis的不是上面建立的那个reds链接哦!而是red;后面会传进来的(因为要操作两个不同的db,我在文档中没有看到切换db的方法,只好这么用了,知道的小伙伴儿留言一下)。 spidername获取方式后面也会说的。 还有剩余的更新Cookie 删除无法使用的账号等,大家伙可以自己试着写写(写不出来也没关系 不影响正常使用) 好啦!搞定!简直So Easy!!!! 现在开始大业了!重写cookie中间件;估摸着吧!聪明的小伙儿看了上面重写User-Agent的方法,十之八九也知道怎么重写Cookie中间件了。 好啦,现在继续写middlewares.py啦!
1 |
class CookieMiddleware(RetryMiddleware): |
第一行:不说 第二行第三行得说一下 这玩意儿叫重载(我想了大半天都没想起来叫啥,还是问了大才。尴尬)有啥用呢: 也不扯啥子高深问题了,小伙伴儿可能发现,当你继承父类之后;子类是不能用 def init()方法的,不过重载父类之后就能用啦! 第四行:settings[‘REDIS_URL’]是个什么鬼?这是访问scrapy的settings。怎么访问的?下面说 第五行:往redis中添加cookie。第二个参数就是spidername的获取方法(其实就是字典啦!)
1 |
@classmethod |
这个貌似不好理解,作用看下面: 这样是不是一下就知道了?? 至于访问settings的方法官方文档给出了详细的方法: http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/settings.html#how-to-access-settings
下面就是完整的middlewares.py文件:
1 |
# -*- coding: utf-8 -*- |
存储我也不写啦!就是这么简单一个分布式的scrapy就这么完成啦!!! 我试了下 三台机器 两个小时 就把整个站点全部爬完了。 弄好你的存储 放在不同的机器上就可以跑啦! 完整的代码在GitHub上: GitHub:https://github.com/thsheep/haoduofuli Y(^o^)Y完工 下篇博文来对付爬虫的大敌:Ajax 以后的教程用微博做靶子,那些数据比较有用,可以玩玩分析什么的。