scrapy Spider CrawlSpider redis 总汇以及一些源码分析

scrapy流程
scrapy 流程图

 

玩scrapy 时,一直看着这张图就ok.

scrapy需要的基础 : lxml ( xpath) ,  关键字 yield ( 生成器)  . 生成器我的博客中有很多文章.可以自己去找 .

 

下面先说一下scrapy的全貌:

一个最简单的Spider : 基本上你用scrapy创建的跟我的差不多.

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['chouti.com']
    start_urls = ['https://dig.chouti.com/']

    def parse(self, response):
        print("return : ",response.url , response.meta)
        yield response.meta

先说一下大致的流程:

1 . Spider.start_requests  读取 start_urls  每次yield 一个Request , 这个Request 将被传递到(每个)Spider中间件(Spider middlewares,看图)  , 在Spider中间件中执行  process_start_requests  处理( yield )每个Request .接下来到了调度器中, 由调度器传递给 (每个) 下载中间件(Downloader middlewares)  , 每个下载中间件将调用 process_request (这一步往往我们会用的比较多,

比如修改Header , User-Agent, Proxy 等等) ,之后就真正去下载网页了.

 

2. 等到网页下载完成后, 将回到(每个) 下载中间件的  process_response ,意思是返回前你还需要对response做点什么.默认直接返回。接着再次通过 (每个)Spider中间件 的 process_spider_input ,意思是你还有次机会能处理response .最后回到 parse函数.

 

3.在上面的代码中有一句yield response.meta  这一步的流程是 :  通过(每个)Spider中间件的 process_spider_output 传递给

(每个) pipelines (常常用于过滤/清洗数据, 以及保存到文件或数据库) 的 process_item . 附注: item 你可以完全把他当成dict使用.

 

这3个步骤基本就是Scrapy的执行流程. 上面的叙述中我都使用了(每个)的意思是, 这些中间件和pipelines 都可以创建多个.

然后在settings.py 中指定其调用顺序.

比方有这么一个下载中间件:

#代理中间件 属于下载中间件
class xProxy(HttpProxyMiddleware):
    def __init__(self,encodeing):
        super().__init__(encodeing)
        self.PROXIES = ['http://183.207.95.27:80', 'http://111.6.100.99:80', 
                   'http://60.31.239.166:3128', 'http://114.55.31.115:3128']

    def process_request(self, request, spider):
        import random
        request.meta['proxy'] =random.choice(self.PROXIES)
        super().process_request(request,spider)


#指定User-agent 中间件 属于下载中间件
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
class RandomUserAgent:
    def __init__(self):
        self.user_agents = ['MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)        Chrome/45.0.2454.101 Safari/537.36"]


    def process_request(self, request, spider):
        print('->RandomUserAgent process_request')
        import random
        request.headers['User-Agent'] =  random.choice(self.user_agents)

内部2个类, 一个用于选择代理, 一个用于选择USER-AGENT .  他们2 都属于下载中间件. 

因此 . 在setting.py 中指定这样的顺序:

# DOWNLOADER_MIDDLEWARES = {
#    'testscrapy.middlewares.RandomUserAgent': 540,
#     'testscrapy.proxymiddleware.xProxy':541
# }

那么RandomUserAgent中的process_request 将先调用. 而后将调用xProxy.process_request.

这种顺序通用于scrapy中的各个组件.  比如Spider中间件, pipelines.  

在scrapy 中你会发现有很多依赖创建的函数  :  from_crawler / from_settings 类方法 ,以及process_xxx的处理函数. 大多数情况下,在后期编写过程中你也发现这些. 最后说一下扩展. 扩展依赖信号.

比如:

from scrapy import signals
from scrapy.crawler import Crawler

class Extention :
    def __init__(self,crawler):
        self.crawler = crawler
        self.settings = crawler.settings

    
    #scrapy将使用 from_crawler 来依赖创建对象
    @classmethod
    def from_crawler(cls, crawler):

        #创建这个扩展
        obj = cls(crawler)
        
        #通过信号来调用
        #如果spider 打开时
        crawler.signals.connect(obj.opened , signal=signals.spider_opened)
        #如果spider 结束
        crawler.signals.connect(obj.closed,signal=signals.spider_closed)
        #如果spider 有一item 被pipeline接受了
        crawler.signals.connect(obj.item_pushed,signal=signals.item_scraped)

        return obj


    def item_pushed(self,item,spider,response):
        print('Extention item pushed : ', item, spider.name ,response)
    def opened(self,spider):
        print('Extention opened name:%s'%spider.name)

    def closed(self,spider):
        print('Extention closed name:%s'%spider.name)

 

到此为止. 基本的scrapy全貌已经说完;

 

正式的教程:

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'            # 爬虫名字 , 全局唯一
    allowed_domains = []       #允许的域名, 空为都可以爬取,如果填上chouti.com,则只能爬chouti

    start_urls = ['https://dig.chouti.com/']    #父类start_requests将循环这个变量


    #当然你可以修改父类的start_requests
    #源码类似于
#    def start_requests(self):
#        for url in self.start_urls:
#           yield url

    def parse(self, response):                #访问完成后将回到这个默认函数中
        print("return : ",response.url , response.meta)
        # yield response.meta

        #call_back 指定回调函数 . 默认情况parse 
        yield Request("https://www.baidu.com",callback=self.process_baidu)

    def process_baidu(self , response):
        print("return : ", response.url, response.meta)

上面你唯一需要注意的就是 name ,全局唯一, scrapy 启动将读取spiders 下的文件. 根据你所指定的 name 来启动爬虫.

只与name字段有关,与类名,文件名都无关

 

可以自己再次发出请求 , 并指定要处理结果的函数(callback) . 由于twisted机制, 你需要使用yield 而不是 return ;

把这些函数当成生成器来使用.

 

pipelines: 用于数据存储 

初学时只需要写一个函数即可 : process_item .

当然里面还有open_spider  当spider被开启时做点事, from_crawler 可以根据配置文件来创建这个对象等等.具体可查看文档.

一个最简单的 pipeline :

class pipeline1(object):
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值