scrapy请求传参、提高爬取效率、中间件、user-agent池、分布式爬虫

scrapy请求传参、提高爬取效率、中间件、user-agent池、分布式爬虫

1. scrapy请求传参

    def parse(self, response):
        div_list = response.css('div.post_item')
        for div in div_list:
            item = ScrItem()
            dec = div.css('p.post_item_summary::text').extract()[-1]
            author = div.css('.post_item_foot a::text').extract_first()
            item['author'] = author
       # 将数据存入meta中,callback调用下一个函数
       yield Request(url, callback=self.parse_detail, meta={'item':item})
        next_page = response.css('div.pager a:last-child::attr(href)').extract_first()
        yield Request(next_page)

    def parse_detail(self, response):
     # 将数据取出 item
= response.meta.get('item') content = response.css('#cnblogs_post_body').extract_first() item['content'] = content yield item

2. 提高爬取效率

在配置文件中配置相关配置即可

1、增加并发:默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改

CONCURRENT_REQUESTS = 100  # 并发设置成100

2、提高日志级别:在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写

LOG_LEVEL='ERROR'

3、禁止cookie:如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:

COOKIES_ENABLED = False

4、禁止重试:对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:

RETRY_ENABLED = False

5、减小下载超时:如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:

DOWNLOAD_TIMEOUT = 10   # 超时时间为10s

3. fake-useragent

请求头中的携带的useragent,搞一个ua池然后随机返回一个,有对应的模块简单使用就好

安装:pip3 install fake-useragent

使用:

from fake_useragent import UserAgent
ua=UserAgent(verify_ssl=False)
print(ua.random)   # 随机生成一个useragent

4. 中间件

有爬虫中间件与下载中间件,一般用的最多的就是下载中间件

1. 下载中间件

1、在配置中配置

# 爬虫中间件
SPIDER_MIDDLEWARES = {
   'scr.middlewares.ScrSpiderMiddleware': 543,
}

# 下载中间件
DOWNLOADER_MIDDLEWARES = {
   'scr.middlewares.ScrDownloaderMiddleware': 543,
}

2、在middlewares.py中写中间件

下载中间件主要有三个方法:

    -process_request:(请求去的时候,走)
        # - return None: 继续处理当次请求,进入下一个中间件
        # - return Response: 当次请求结束,把Response丢给引擎处理(可以自己爬,包装成Response)
        # - return Request : 相当于把Request重新给了引擎,引擎再去做调度
        # - 抛异常:执行process_exception
  -process_response:(请求回来的时候,走)
        # - return a Response object :继续处理当次Response,继续走后续的中间件
        # - return a Request object:重新给引擎做调度
        # - or raise IgnoreRequest :process_exception
  -process_exception:(出异常,走)
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain  :停止异常处理链,给引擎(给爬虫)
        # - return a Request object: stops process_exception() chain :停止异常处理链,给引擎(重新调度)
    # 获取代理函数
    def get_proxy(self):
        import requests
        proxy = requests.get('代理地址/get').json()['proxy']
        return proxy

    def process_request(self, request, spider):
        # 1 加cookie(在request.cookies中就是访问该网站的cookie)
        print(request.cookies)
        #从你的cookie池中取出来的,  字典,设置
        request.cookies={'k':'v'}
        print(request.cookies)
        
        # 2 加代理 在request.meta['proxy']中加
        request.meta['proxy'] = self.get_proxy()
        
        # 3 修改useragent
        from fake_useragent import UserAgent
        ua = UserAgent(verify_ssl=False)
        request.headers['User-Agent'] = ua
        
        return None
process_request中加cookie与加代理与加useragent
    def process_exception(self, request, exception, spider):
        # 如果url错误在这不能直接修改url
        # request.url = 'http://www.cnblogs.com/'
        # 如果想在中间件中修改url必须引入Request做修改, 也可以做回调
        from scrapy.http import Request
        return Request('http://www.cnblogs.com/')
        # return Request('http://www.cnblogs.com/', callback=spider.parse_detail)
process_exception中处理异常

集成selenium可以在 process_request 和 process_response 中做,在process_request 中做效率更高

1. 在爬虫中创建bro对象和关闭爬虫

    # 在爬虫中创建bro对象
    bro = webdriver.Chrome(executable_path='E:\Python\scr\chromedriver.exe')
    # 关闭,在爬虫中
    def close(self, reason):
        self.bro.close()

2. 在中间件中使用selenium解析并返回

        from scrapy.http import HtmlResponse
        spider.bro.get(request.url)
        text = spider.bro.page_source
        response = HtmlResponse(url=request.url, body=text.encode('utf8'))

        return response

 5. bitmap去重与布隆过滤器原理

1. bitmap去重

通过一个比特位来存一个地址,占用内存很小

2. 布隆过滤器

BloomFilter 会开辟一个m位的bitArray(位数组),开始所有数据全部置 0 。当一个元素过来时,能过多个哈希函数(h1,h2,h3....)计算不同的在哈希值,并通过哈希值找到对应的bitArray下标处,将里面的值 0 置为 1 。

Python中使用布隆过滤器

#python3.6 安装
#需要先安装bitarray
pip3 install bitarray-0.8.1-cp36-cp36m-win_amd64.whl(pybloom_live依赖这个包,需要先安装)
#下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
pip3 install pybloom_live

示例一

#ScalableBloomFilter 可以自动扩容
from pybloom_live import ScalableBloomFilter

bloom = ScalableBloomFilter(initial_capacity=100, error_rate=0.001, mode=ScalableBloomFilter.LARGE_SET_GROWTH)
url = "www.cnblogs.com"
url2 = "www.baidu.com"
bloom.add(url)

print(url in bloom)
print(url2 in bloom)

示例二

#BloomFilter 是定长的
from pybloom_live import BloomFilter

bf = BloomFilter(capacity=1000)
url='www.baidu.com'
bf.add(url)

print(url in bf)
print("www.cnblogs.com" in bf)

6. 分布式爬虫

安装:pip3 install scrapy-redis

1. 原来的爬虫继承并修改start_urls

# 1 原来的爬虫继承
from scrapy_redis.spiders import RedisSpider
class CnblogsSpider(RedisSpider):
      #start_urls = ['http://www.cnblogs.com/']
    redis_key = 'myspider:start_urls'

2. 在settings中配置

# 2 在setting中配置
  SCHEDULER = "scrapy_redis.scheduler.Scheduler"
  DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 这里可以不配就走每一个的数据库,配置了就走公用的数据库
  ITEM_PIPELINES = {
     'scrapy_redis.pipelines.RedisPipeline': 300
  }
# REDIS_HOST = 'localhost'
# REDIS_PORT = 6379
# REDIS_ENCODING = 'utf8'
REDIS_PARAMS = {'password':'2694'}

3. 多台机器启动爬虫

4. 通过命名向redis中发送起始url

redis-cli
auth password
lpush myspider:start_urls https://www.cnblogs.com

 

posted @ 2020-04-12 19:53  Mr沈  阅读(338)  评论(0编辑  收藏  举报