05. 爬虫之scrapy参数配置和持久化

一、配置参数

# 是否遵循爬虫协议
ROBOTSTXT_OBEY = False
# 浏览器类型(,默认写的是scrapy)
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
# 3、日志级别(默认是info,执行爬虫项目,info会被打印出来)、
# 设置成ERROR,只打印错误信息(提高爬虫效率)
LOG_LEVEL='ERROR'

二、scrapy持久化

# 1 scrapy crawl cnblogs -o cnblogs.json  (这个不需要记)
	1 在items中写类,类中写字段
      class CnblogsSpiderItem(scrapy.Item):
          title = scrapy.Field()
          desc=scrapy.Field()
          url=scrapy.Field()
          author=scrapy.Field()
          # 重点(文章详情,如果跟之前爬过的文章对应)
          content=scrapy.Field()
  	2 在爬虫中把要保存的字段放到item对象中
      article_item['url']=url
      article_item['title']=title
      article_item['desc']=desc
      article_item['author']=author
      yield article_item	
      
  	3 在控制台输入:scrapy crawl cnblogs -o cnblogs.json


# 2 常用方式,只记住这一种
	1 在items中写类,类中写字段
      class CnblogsSpiderItem(scrapy.Item):
          title = scrapy.Field()
          desc=scrapy.Field()
          url=scrapy.Field()
          author=scrapy.Field()
          # 重点(文章详情,如果跟之前爬过的文章对应)
          content=scrapy.Field()
 	2 在爬虫中把要保存的字段放到item对象中
      article_item['url']=url
      article_item['title']=title
      article_item['desc']=desc
      article_item['author']=author
      yield article_item	
	3 在setting中配置
      ITEM_PIPELINES = {
       'cnblogs_spider.pipelines.CnblogsSpiderFilePipeline': 300,  # 数字表示优先级,数字越小,优先级越大
       'cnblogs_spider.pipelines.CnblogsSpiderMysqlPipeline': 400,  # 数字表示优先级,数字越小,优先级越大
    	}
	4 在pipline中写
    class CnblogsSpiderFilePipeline:
      # 爬虫启动他会执行
      def open_spider(self,spider):
          # spider是爬虫对象
          print(spider.name)
          print('爬虫开始了')
          self.f=open('cnblogs.txt','w',encoding='utf-8')
      def close_spider(self,spider):
          # 爬虫停止会执行
          print('爬虫停止了')
          self.f.close()
      def process_item(self, item, spider):
          self.f.write(item['title']+item['desc']+item['author']+item['url'])
          self.f.write('/n')
          return item


  import pymysql
  class CnblogsSpiderMysqlPipeline:

      def open_spider(self,spider):
          self.conn=pymysql.connect( host='127.0.0.1', user='root', password="123",database='cnblogs', port=3306)
          self.cursor=self.conn.cursor()
      def close_spider(self,spider):
          self.conn.commit()
          self.cursor.close()
          self.conn.close()
      def process_item(self, item, spider):
          sql='insert into aritcle (title,`desc`,url,author) values (%s,%s,%s,%s )'
          self.cursor.execute(sql,args=[item['title'],item['desc'],item['url'],item['author']])
          return item

三、请求传递参数

# 1、给另一个请求传递参数,在响应中拿到(借助meta)
	yield Request(url=url, callback=self.parser_detail, meta={'item':article_item})
  
# 2、在解析方法中通过response对象获取
	item=response.meta.get('item')

四、提高爬虫效率

提高scrapy的爬取效率(scrapy是异步框架,基于twisted,性能其实已经很高了),
可以优化的点:

- 在配置文件中进行相关的配置即可:(默认还有一套setting,类比django)
#1 增加并发:
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS值为100,并发就设置成了为100:
CONCURRENT_REQUESTS = 100

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

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

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

# 5 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中修改超时时间(单位为秒):
DOWNLOAD_TIMEOUT = 10    # 超时时间为10s	

五、scrapy中间件

1、下载中间件 CnblogsSpiderDownloaderMiddleware

process_request方法:

1 请求来的时候
'''
Must either:
- return None: continue processing this request     返回None,进入下一个下载中间件的process_request
- or return a Response object                       返回response对象,会给引擎,引擎给爬虫,进入解析
- or return a Request object                        返回请求对象,会给引擎,引擎给调度器,放到调度器
- or raise IgnoreRequest: process_exception() methods of 抛异常,就会触发process_exception的执行
'''

# 总结:
  返回None,继续爬取
  返回Resoponse对象,会给引擎,再交给爬虫,去解析
  返回Request对象,会给引擎,给调度器,等待下一次被调度
  
# 什么情况会用下载中间件:
  加代理,加cookie,加浏览器类型
  集成 selenium
  
# 修改cookie
  request.cookies={'name':'jason'}
  
# 使用代理
  proxy='http://154.16.63.16:8080'  # 从代理池中获取
  request.meta["proxy"] =proxy
  
# 修改请求头
  request.headers.setlist(b'User-Agent','asdfasdf')

2、爬虫中间件

了解即可

六、集成selenium

# 1、在爬虫中写:
class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['www.bilibili.com']
    start_urls = ['https://www.bilibili.com/v/dance/otaku/#/all/default/0/1/']
    bro = webdriver.Chrome(executable_path='./chromedriver')
    bro.implicity_wait(10)
    @staticmethod
    def close(spider, reason):
        spider.bro.close()
        
# 2、在中间件中直接使用
class CnblogsSpiderDownloaderMidddleware:
    def process_request(self, request, spider):
        spider.bro.get(request.url)
        response = HtmlResponse(url=request.url, body=bytes(spider.bro.page_source, encoding='utf-8'))
        return response
   
# 隐藏浏览器(无头浏览器)

七、去重规则

1、scrapy使用的去重

# 1、scrapy默认会去重,使用了RFPDupeFilter
from scrapy.dupefilters import RFPDupeFilter

# 2、在默认的settings中配置

# 3、本质原理是使用的集合去重

# 4、更高级部分:
	将url的?后面的部分打散了再排序:
     示例:
		127.0.0.1/?name=lqz&age=19
		127.0.0.1/?age=19&name=lqz
        这两个其实是同一个网址,但是如果直接将url放进集合中是不能去重的
    # 本质原理:
    	fp = self.request_fingerprint(request)  # 得到一个指纹,上面那两个地址得到的结果就是一样的

2、自定义去重规则

# 如果自己要写一个去重类,如何使用?
- 写一个类,继承BaseDupeFilter,重写def request_seen(self, request):
- 返回True 表示爬虫过了
- 返回False 表示没有爬过

# 跟高级的去重方案:
- 集合去重的问题:当需要处理的地址特别多时(比如上亿个地址),集合就会变得特别大,会非常占内存
- 布隆过滤器,可以用极小内存完成大量去重
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值