zoukankan      html  css  js  c++  java
  • scrapy入门(二)请求传参和中间件

    1. scrapy的请求传参

      作用 : 实现深度爬取

      使用场景 : 爬取的数据没有在同一张页面

      例如, 爬取电影首页全部电影的详情页信息

      #请求传参: 让Request将一个数据值(字典)传递给回调函数
      #在第一页中将item对象的第一个属性赋值,然后通过请求传参将item对象传过去
      model_index = [3,4,6,7,8]
      for index in model_list:
       li =li_list[index]
       model_url = li.xpath('xxxxxxx').extract_first()
       self.model_urls.append(model_url)
      #for li in li_list:  #这种适用于所有的li标签都需要的情况下,当只需要某几个标签时,选用上面的方式
       #...
       #手动发送get请求,通过请求传参将item对象以字典值的形式传给my_parse:
      	yield scrapy.Request(url=, callback=my_parse, meta={'item':item})
      if self.page < 5:
       self.page += 1
       new_url = format(self.url%self.page)
       yield scrapy.Request(url=new_url,callback=parse)
      
      
      
      def my_parse(self, response):
       #接受请求传参的数据,还原出item对象
       item = response.meta['item']
      	#解析item对象需要的第二个属性
       xxx = respnse.xpath('').extract_first()
       #给item对象的第二个属性赋值
       item['xxx'] = xxx
       #还可以接着请求传参,这里不再演示
       yield item
      
    2. scrapy的中间件, 和管道一样, 需要在配置文件中开启中间件

      下载中间件 : 批量拦截requests和response

      作用:

      • 修改请求的头信息
      • 修改请求的ip地址 (代理模式)
      • 修改响应对象(数据)

      middlewares.py文件: 修改成如下形式

      import scrapy
      
      #构建UA池,这样可以不在settings文件中写死
      user_agent_list = [
          'xxxxxx',
          'xxxxxxxxx',
          'xxxxxxxxxxxxxxxxxxx'
      ]
      class SecondtestDownloaderMiddleware(object):
          #拦截正常请求
          def process_request(self, request, spider):
      		#进行UA伪装,构建UA池
              request.headers['User-Agent'] = random.choice(user_agent_list)
              
              #代理,也可以构建自己的代理池
              request.meta['proxy'] = 'xxxxxxxxxxxx'
              return None
      	#拦截所有的响应
          def process_response(self, request, response, spider):
      		#拦截由于动态加载得到的不符合需求的响应对象
              #request表示请求对应的??对象
              #response表示所有的响应对象
              #spider是SecondSpider类(爬虫源文件对应的类)的实例化对象
              if request.url in spider.model_urls:
                  #body 有selenium中的page_source返回
                  browser = spider.browser
                  browser.get(request.url)
                  sleep(3)
                  page_text = browser.page_source
                  new_response = HtmlResponse(url=request.url,body=page_text,encoding ='utf-8',request=request)
                  return new_response
              else:
                  return response
              return response
      	#拦截发生异常的请求对象
          def process_exception(self, request, exception, spider):
      		#对异常的url请求进行修正
              return request		#重新发送
      

      源文件中进行修改

      #在爬虫类中定义一个属性model_urls =[]用来保存解析得到的li标签的url
      #
      from selenium import webdriver
      
      class xxx(scrapy.Spider):
          name = ''
          model_urls =[]
          browser = webdriver.Chrome(executable_path ='')
          #下面三个函数调用过程中可能出现请求传参的情况
          def parse(self,response):
              pass
          def parse_model(self,response):
              pass
          def parse_new_detail(self,response):
              content = response.xpath('xxxx//text()').extract()#解析所有的文本内容,跨标签,返回的是列表
              content = ''.jion(content)
              pass
        #该方法只会在程序结束时调用一次
        def closed(self,spider):
          self.browser.quit()
      
    3. 提升爬取效率

      • 增加并发: 32---->100
      • 降低日志等级
      • 不需要cookie的时候可以禁止,默认是开启. 设置为COOKIES_ENABLED = False为禁止
      • 禁止重试RETRY_ENABLED = False
      • DOWNLOAD_TIMEOUT = 1
  • 相关阅读:
    浅入了解GCD 并发 并行 同步 异步 多线程
    XSD
    想在Images.xcassets 只能用 imageNamed 加载里边的素材 其他方法 你就别费老劲了
    如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件
    编译 wxWidgets3.0.2 on Mac OS X Yosemite 出错?!的解决方法
    3、技术积累方面总结
    2、日常计划管理总结
    站在客户的角度考虑问题
    公司管理的一点思虑
    项目管理一定要规范阿
  • 原文地址:https://www.cnblogs.com/yimeisuren/p/12417116.html
Copyright © 2011-2022 走看看