社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  分享发现

小白进阶之Scrapy(基于Scrapy-Redis的分布式以及cookies池)

芝麻HTTP代理 • 7 年前 • 1892 次点击  

首先我们更新一下scrapy版本。最新版为1.3

再说一遍Windows的小伙伴儿 pip是装不上Scrapy的。推荐使用anaconda 、不然还是老老实实用Linux吧。

conda install scrapy==1.3
或者
pip install scrapy==1.3

安装Scrapy-Redis

conda install scrapy-redis

或者

pip 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中的!

#启用Redis调度存储请求队列

SCHEDULER = "scrapy_redis.scheduler.Scheduler"



#确保所有的爬虫通过Redis去重

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"



#默认请求序列化使用的是pickle 但是我们可以更改为其他类似的。PS:这玩意儿2.X的可以用。3.X的不能用

#SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"



#不清除Redis队列、这样可以暂停/恢复 爬取

#SCHEDULER_PERSIST = True



#使用优先级调度请求队列 (默认使用)

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

#可选用的其它队列

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'



#最大空闲时间防止分布式爬虫因为等待而关闭

#这只有当上面设置的队列类是SpiderQueue或SpiderStack时才有效

#并且当您的蜘蛛首次启动时,也可能会阻止同一时间启动(由于队列为空)

#SCHEDULER_IDLE_BEFORE_CLOSE = 10



#将清除的项目在redis进行处理

ITEM_PIPELINES = {

    'scrapy_redis.pipelines.RedisPipeline': 300

}



#序列化项目管道作为redis Key存储

#REDIS_ITEMS_KEY = '%(spider)s:items'



#默认使用ScrapyJSONEncoder进行项目序列化

#You can use any importable path to a callable object.

#REDIS_ITEMS_SERIALIZER = 'json.dumps'



#指定连接到redis时使用的端口和地址(可选)

#REDIS_HOST = 'localhost'

#REDIS_PORT = 6379



#指定用于连接redis的URL(可选)

#如果设置此项,则此项优先级高于设置的REDIS_HOST 和 REDIS_PORT

#REDIS_URL = 'redis://user:pass@hostname:9001'



#自定义的redis参数(连接超时之类的)

#REDIS_PARAMS  = {}



#自定义redis客户端类

#REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'



#如果为True,则使用redis的'spop'进行操作。

#如果需要避免起始网址列表出现重复,这个选项非常有用。开启此选项urls必须通过sadd添加,否则会出现类型错误。

#REDIS_START_URLS_AS_SET = False



#RedisSpider和RedisCrawlSpider默认 start_usls 键

#REDIS_START_URLS_KEY = '%(name)s:start_urls'



#设置redis使用utf-8之外的编码

#REDIS_ENCODING = 'latin1'

看不下去的小伙伴儿看这儿:http://scrapy-redis.readthedocs.io/en/stable/readme.html请各位小伙伴儿自行挑选需要的配置写到项目的settings.py文件中。

继续在我们上一篇博文中的爬虫程序修改:

首先把我们需要的redis配置文件写入settings.py中:

如果你的redis数据库按照前一片博文配置过则需要以下至少三项

SCHEDULER = "scrapy_redis.scheduler.Scheduler"



DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"



REDIS_URL = 'redis://root:密码@主机IP:端口'

Nice配置文件写到这儿。我们来做一些基本的反爬虫设置第三项请按照你的实际情况配置。

最基本的一个切换UserAgent!

首先在项目文件中新建一个useragent.py用来写一堆 User-Agent(可以去网上找更多,也可以用下面这些现成的)

agents = [

    "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Avant Browser/1.2.789rel1 (http://www.avantbrowser.com)",

    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5",

    "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9",

    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7",

    "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14",

    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14",

    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20",

    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27",

    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1",

    "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2",

    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7",

    "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre",

    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10",

    "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)",

    "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB5",

    "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)",

    "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",

    "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",

    "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0",

    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110622 Firefox/6.0a2",

    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1",

    "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100815 Minefield/4.0b4pre",

    "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )",

    "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)",

    "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a",

    "Mozilla/2.02E (Win95; U)",

    "Mozilla/3.01Gold (Win95; I)",

    "Mozilla/4.8 [en] (Windows NT 5.1; U)",

    "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko Netscape/7.1 (ax)",

    "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0",

    "Mozilla/5.0 (Linux; U; Android 1.5; en-us; sdk Build/CUPCAKE) AppleWebkit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 1.5; en-us; htc_bahamas Build/CRB17) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 2.1-update1; de-de; HTC Desire 1.19.161.5 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 1.5; de-ch; HTC Hero Build/CUPCAKE) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 2.1; en-us; HTC Legend Build/cupcake) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    


    
"Mozilla/5.0 (Linux; U; Android 1.5; de-de; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 FirePHP/0.3",

    "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10  (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",

    "Mozilla/5.0 (Linux; U; Android 1.5; en-us; T-Mobile G1 Build/CRB43) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari 525.20.1",

    "Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile_G2_Touch Build/CUPCAKE) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.0.1; de-de; Milestone Build/SHOLS_U2_01.14.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10  (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",

    "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522  (KHTML, like Gecko) Safari/419.3",

    "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10  (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",

    "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",

    "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",

    "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10  (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",

    "Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

    "Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10i Build/R1AA056) AppleWebKit/528.5  (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",

现在我们来重写一下Scrapy的下载中间件(哇靠!!重写中间件 好高端啊!!会不会好难!!!放心!!!So Easy!!跟我做!包教包会,毕竟不会你也不能顺着网线来打我啊):

关于重写中间件的详细情况 请参考官方文档:

http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/downloader-middleware.html#scrapy.contrib.downloadermiddleware.DownloaderMiddleware

在项目中新建一个middlewares.py的文件(如果你使用的新版本的Scrapy,在新建的时候会有这么一个文件,直接用就好了)

首先导入UserAgentMiddleware毕竟我们要重写它啊!

import json ##处理json的包

import redis #Python操作redis的包

import random #随机选择

from .useragent import agents #导入前面的

from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware #UserAegent中间件

from scrapy.downloadermiddlewares.retry import RetryMiddleware #重试中间件

开写:

class UserAgentmiddleware(UserAgentMiddleware):



    def process_request(self, request, spider):

        agent = random.choice(agents)

        request.headers["User-Agent"] = agent

第一行:定义了一个类UserAgentmiddleware继承自UserAgentMiddleware

第二行:定义了函数process_request(request, spider)为什么定义这个函数,因为Scrapy每一个request通过中间件都会调用这个方法。

QQ20170206-223156

第三行:随机选择一个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:

首先日常导入我们需要的文件:

import requests

import json

import redis

import logging

from .settings import REDIS_URL ##获取settings.py中的REDIS_URL

首先我们把登陆用的账号密码 以Key:value的形式存入redis数据库。不推荐使用db0(这是Scrapy-redis默认使用的,账号密码单独使用一个db进行存储。)

QQ20170207-221128@2x

就像这个样子。

解决第一个问题:获取Cookie:

import requests

import json

import redis

import logging

from .settings import REDIS_URL



logger = logging.getLogger(__name__)

##使用REDIS_URL链接Redis数据库, deconde_responses=True这个参数必须要,数据会变成byte形式 完全没法用

reds = redis.Redis.from_url(REDIS_URL, db=2, decode_responses=True)

login_url = 'http://haoduofuli.pw/wp-login.php'



##获取Cookie

def get_cookie(account, password):

    s = requests.Session()

    payload = {

        'log': account,

        'pwd': password,

        'rememberme': "forever",

        'wp-submit': "登录",

        'redirect_to': "http://http://www.haoduofuli.pw/wp-admin/",

        'testcookie': "1"

    


    
}

    response = s.post(login_url, data=payload)

    cookies = response.cookies.get_dict()

    logger.warning("获取Cookie成功!(账号为:%s)" % account)

    return json.dumps(cookies)

这段很好懂吧。

使用requests模块提交表单登陆获得Cookie,返回一个通过Json序列化后的Cookie(如果不序列化,存入Redis后会变成Plain Text格式的,后面取出来Cookie就没法用啦。)

第二个问题:将Cookie写入Redis数据库(分布式呀,当然得要其它其它Spider也能使用这个Cookie了)

def init_cookie(red, spidername):

    redkeys = reds.keys()

    for user in redkeys:

        password = reds.get(user)

        if red.get("%s:Cookies:%s--%s" % (spidername, user, password)) is None:

            cookie = get_cookie(user, password)

            red.set("%s:Cookies:%s--%s"% (spidername, user, password), cookie)

判断这个spider和账号的Cookie是否存在,不存在 则调用get_cookie函数传入从redis中获取到的账号密码的cookie;使用我们上面建立的redis链接获取redis db2中的所有Key(我们设置为账号的哦!),再从redis中获取所有的Value(我设成了密码哦!)

保存进redis,Key为spider名字和账号密码,value为cookie。

这儿操作redis的不是上面建立的那个reds链接哦!而是red;后面会传进来的(因为要操作两个不同的db,我在文档中没有看到切换db的方法,只好这么用了,知道的小伙伴儿留言一下)。

spidername获取方式后面也会说的。

还有剩余的更新Cookie 删除无法使用的账号等,大家伙可以自己试着写写(写不出来也没关系 不影响正常使用)

好啦!搞定!简直So Easy!!!!

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/4858
 
1892 次点击