Python分布式爬虫打造搜索引擎(四)

Python分布式爬虫打造搜索引擎


 一、scrapy进阶开发

 1、selenium相关学习:https://www.cnblogs.com/Eric15/p/9884309.html

 2、selenium集成到scrapy中

  下载中间件的process_request和process_response方法

  ①、process_request:每个交给下载器的request对象都会经过该方法,并期望返回response(每爬取一个url前,都会执行此方法)

  ②、 process_response:当下载器完成http请求,返回响应给引擎的时候调用

 对一些动态网站,获取数据时采用selenium/phantomjs实现。集成selenium到scrapy框架中,只需要在middleware.py中新建中间件类,在其中实现process_request方法就可以了:

# middleware.py
from selenium import webdriver
from scrapy.http import HtmlResponse
class JSPageMiddleware(object):

    #通过selenium - chrome请求动态网页
    def process_request(self, request, spider):
    # 每次进行url请求时,都会调用此方法(前提setting中需配置)
        if spider.name == "jobbole":  # 爬取伯乐时执行
            # browser = webdriver.Chrome(executable_path="C:/chromedriver.exe")
            spider.browser.get(request.url)
            import time
            time.sleep(3)
            print ("访问:{0}".format(request.url))

          # 返回HtmlResponse,可以结束当条爬虫对下载中间件中其他类的执行,
            return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source, encoding="utf-8", request=request)  #HtmlResponse中这几个参数都是必须的,固定写法

    process_response(self):
    # 每条数据爬取完成后调用
        pass

 

 关于控制浏览器打开关闭,可在爬虫主文件处理。首先需引人dispatcher/sigals

dispatcher.connect:信号的映射

 导入:from scrapy.xlib.pydispatch import dispatcher

signals:信号量,非常重要

 导入:from scrapy import signals

 使用:

from scrapy.xlib.pydispatch import dispatcher
from scrapy import signals
    #使用selenium
    
    def __init__(self):
    # 会将driver封装进spider中
        self.browser = webdriver.Chrome(executable_path="D:/Temp/chromedriver.exe")
        super(JobboleSpider, self).__init__()
        # 信号的映射,spider_closed:当爬虫结束时执行self.spider_closed方法
        dispatcher.connect(self.spider_closed, signals.spider_closed)
    
    def spider_closed(self, spider):
        #当爬虫退出的时候关闭chrome
        print ("spider closed")
        self.browser.quit()

 

 setting.py中配置:

DOWNLOADER_MIDDLEWARES = {
'ArticleSpider.middlewares.JSPageMiddleware': 1,

#    'ArticleSpider.middlewares.RandomUserAgentMiddlware': 543,
#    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}

需要注意的是:以上述方式运行爬虫相关,当执行到selenium相关操作部分时,便不再是异步操作而是同步的了。当然,也可以通过twisted集成实现异步操功能。


 

3、scrapy的暂停与重启

前提:进入爬虫目录

启动/重启爬虫:

scrapy crawl jobbole -s JOBDIR=jobs/001

JOBDIR=jobs/001:启动爬虫时,新建jobs/001目录,用于保存中间态信息;重启爬虫时,会读取001目录中相关信息,进行后续的数据爬取

暂停爬虫:ctrl + c ,按一次表示暂停,按两次表示强制结束。pycharm中没有此功能,一般在终端运行。

jobs/001目录:开始爬取数据后,001目录下会生成如下文件:

在requests.queue目录下也生成两个文件:

文件名类型用处
request.seen文件已经访问过的url
spider.state文件spider的状态信息
requests.queue文件夹request队列
requests.queue/p1文件需要继续做完的request

  

注意:

  • JOBDIR目录下主要是保存中间态信息
  • 不同的spider不能共用同一个目录(另生成目录001、002、003等)
  • 不同的run不能共用同一个目录
  • 不能用kill -9 main.py 命令强制结束爬虫
  • 正常退出使用ctrl+c(只能按一次,按完需要一段时间处理中间状态)

 4、scrapy的数据收集

document:https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/stats.html

[以下是文档概述-scrapy数据收集]

数据收集(Stats Collection)

 Scrapy提供了方便的收集数据的机制。数据以key/value方式存储,值大多是计数值。 该机制叫做数据收集器(Stats Collector),可以通过 Crawler API 的属性 stats 来使用。在下面的章节 常见数据收集器使用方法 将给出例子来说明。

无论数据收集(stats collection)开启或者关闭,数据收集器永远都是可用的。 因此您可以import进自己的模块并使用其API(增加值或者设置新的状态键(stat keys))。 该做法是为了简化数据收集的方法: 您不应该使用超过一行代码来收集您的spider,Scrpay扩展或任何您使用数据收集器代码里头的状态。

 数据收集器的另一个特性是(在启用状态下)很高效,(在关闭情况下)非常高效(几乎察觉不到)。

 数据收集器对每个spider保持一个状态表。当spider启动时,该表自动打开,当spider关闭时,自动关闭。

可用的数据收集器

 除了基本的 StatsCollector ,Scrapy也提供了基于 StatsCollector 的数据收集器。 您可以通过 STATS_CLASS 设置来选择。默认使用的是 MemoryStatsCollector

常见数据收集器的使用方法(通过 stats 属性来使用数据收集器),具体请参考上述文档链接


 

demo:

 爬取伯乐在线文章,截获404,将抓取到的404页面的次数添加到数据收集器中(stats)

在jobbole.py中编写代码:

#收集伯乐在线所有404的url以及404页面数
handle_httpstatus_list = [404]

 scrapy中默认是会过滤掉有问题的HTTP response,除了状态码为200-300的请求及response会被处理外,其他状态码均会被默认过滤掉,不做处理。我们要截获404错误页面,通过response.status == 403判断是没有的,需要使用

handle_httpstatus_list=[404],此时能截获到404页面进行处理(200-300 、404页面给予处理),后面才能根据状态码来判断是否爬取的是404页面,然后才能将数据收集到数据收集器中。

实现每捕获一个404页面,就让数据收集器里的failed_url +1:

class JobboleSpider(scrapy.Spider):
    name = "jobbole"
    allowed_domains = ["blog.jobbole.com"]
    start_urls = ['http://blog.jobbole.com/all-posts/']

    #收集伯乐在线所有404的url以及404页面数
    handle_httpstatus_list = [404]

    def parse(self, response):
        # 捕获到404页面,stats中failed_url数据+1
        if response.status == 404:
            self.fail_urls.append(response.url)
            self.crawler.stats.inc_value("failed_url")  #stats是存在于crawler中的

......
  

 5、scrapy的信号

document:https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/signals.html


 


 

二、scrapy-redis 分布式爬虫

1、scrapy-redis概述

 1)scrapy本身是个通用的爬虫框架,但并不支持分布式爬虫模式。要使用分布式爬虫,则需要使用到scrapy-redis爬虫组件,scrapy-redis提供了一些以redis为基础的组件(仅有组件)。

 2)分布式爬虫的优点:

  1. 可以充分利用多台机器的带宽
  2. 可以充分利用多台机器的ip地址
  3. 多台机器做,爬取效率更高

 3)分布式爬虫必须要解决的问题:

  1. 分布式爬虫是好几台机器在同时运行,如何保证不同的机器爬取页面的时候不会出现重复爬取的问题?
  2. 同样,分布式爬虫在不同的机器上运行,在把数据爬取完成后如何保证保存在同一个地方?

2、scrapy-redis 安装

pip install scrapy-redis

 

3、redis相关操作参考:https://www.cnblogs.com/Eric15/articles/9459329.html


 

4、将scrapy项目变成scrapy-redis项目:

1)将爬虫继承的类:scrapy.Spider,变成继承:scrapy_redis.spiders.RedisSpider ; 如果继承的是scrapy.CrawlSpider类,则变成继承:scrapy_redis.spiders.RedisCrawlSpider。

2)将爬虫中的start_urls删掉/注释,增加redis_key="xxx"。作用:用于控制爬虫启动,爬虫的第一个url就是在redis中通过这个redis_key发送出去的

#demo:
redis_key = "sina_guide:strat_urls" 

 

3)在配置文件中增加以下配置:

# 使用scrapy-redis里的去重组件,不使用scrapy默认的去重方式
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis里的调度器组件,不使用默认的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 允许暂停,redis请求记录不丢失
SCHEDULER_PERSIST = True
# 默认的scrapy-redis请求队列形式(按优先级)
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 队列形式,请求先进先出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# 栈形式,请求先进后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"

# 只是将数据放到redis数据库,不需要写pipelines文件
ITEM_PIPELINES = {
#    'Sina.pipelines.SinaPipeline': 300,
    'scrapy_redis.pipelines.RedisPipeline': 400,
}

# LOG_LEVEL = 'DEBUG'   # 日志打印等级

# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
# DOWNLOAD_DELAY = 1   # 爬虫延迟时间
# 指定数据库的主机IP
REDIS_HOST = "192.168.13.26"
# 指定数据库的端口号
REDIS_PORT = 6379

 

运行爬虫时:

 1)在爬虫服务器上,进入爬虫文件所在的路径,输入运行命令:scrapy runspider [爬虫文件名]↓

#demo:
scrapy runspider sina.py

 

 2)在Redis服务器上,推入一个开始的url链接:redis-cli(客户端进入);推入链接:lpush [redis_key] start_url ,开始爬取↓

#demo:
redis-cli> lpush sina_guide:start_urls http://news.sina.com.cn/guide/  # sina_guide:start_urls 需与上面的start_urls 保持一致

 

转载于:https://www.cnblogs.com/Eric15/articles/9961246.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值