zoukankan      html  css  js  c++  java
  • 爬虫之scrapy高级部分等相关内容-138

    1 配置参数

    #1  是否遵循爬虫协议
    ROBOTSTXT_OBEY = False
    #2 浏览器类型(默认写的是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'

     

    2 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

    3 请求传递参数

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

    4 提高爬虫效率

    1 提高scrapy的爬取效率(异步框架,基于twisted,性能很高了,可以优化的点),面试聊

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

    #2 降低日志级别:
    在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’
    # 3 禁止cookie:(cnblogs不需要cookie)
    如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False
    # 4禁止重试:
    对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:
    RETRY_ENABLED = False
    # 5 减少下载超时:
    如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:
    DOWNLOAD_TIMEOUT = 10 超时时间为10s

     

     

    5 scrapy中间件

    5.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':'lqz'}
     # 使用代理
     proxy='http://154.16.63.16:8080'  # 从代理池中获取
     request.meta["proxy"] =proxy
     # 修改请求头
     request.headers.setlist(b'User-Agent','asdfadsfadsf')

    process_response

    # Must either;
    # - return a Response object       正常逻辑,给 引擎,引擎个爬虫去解析
    # - return a Request object         返回Request对象,给引擎,引擎给调度器,等待下一次被调度
    # - or raise IgnoreRequest         抛异常IgnoreRequest,响应不要了,不会给引擎,再给爬虫解析

    # 总结
    返回Response,正常逻辑走
    返回Request,放到调度器


    # 什么情况会用到
    抛异常,不再解析该响应(用的也不多)

    5.2 爬虫中间件

    了解

    6 集成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.implicitly_wait(10)
         @staticmethod
         def close(spider, reason):
             spider.bro.close()
             
             
    2 在中间件中直接使用
     class CnblogsSpiderDownloaderMiddleware:
         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
           
           
    3 隐藏浏览器?无头浏览器

    7 去重规则

    1 默认会去重,使用了
    from scrapy.dupefilters import RFPDupeFilter
    2 在默认的setting中配的
    3 本身原理是使用的是集合去重

    4 更高级部分
    # 是不是同一个地址
    127.0.0.1/?name=lqz&age=19
    127.0.0.1/?age=19&name=lqz
    # 本质原理,把?后的打散了,再排序
    fp = self.request_fingerprint(request) # 得到一个指纹,上面那两个地址结果一样




    ## 自定义去重规则
    如果你自己写去重类,如何使用?
    写一个类,继承 BaseDupeFilter,重写def request_seen(self, request):
    返回true表示爬过了
    返回false表示没有爬过


    # 你有个更牛逼的去重方案
    -集合去重可以,存在问题,如果地址特别多,上亿个地址,集合会特别大,会非常占用内存
     -极小内存,完成去重(布隆过滤器)

     

  • 相关阅读:
    苹果开发者账号多少钱?个人/公司/企业申请费用及怎么选【都有】
    uniapp ios真机调试【亲测有效】
    Uniapp---IOS打包证书私钥密码怎么获取?
    微信小程序地图计算两个点之间的距离
    各大地理坐标系互转
    解决mac下vscode等应用中vim光标无法快速移动
    python 脚本如何在后代运行并记录标准输出
    wkhtmltox 在Linux上安装
    shell中的##*,%%*问题
    matplotlib、seaborn 展示中文字体
  • 原文地址:https://www.cnblogs.com/usherwang/p/14470901.html
Copyright © 2011-2022 走看看