【问题标题】:how to update response of spider in scrapy如何在scrapy中更新蜘蛛的响应
【发布时间】:2018-11-18 17:34:53
【问题描述】:

我对 SCRAPY 很陌生 我尝试从该网站 (http://quotes.toscrape.com/random) 中提取 100 条引号,为此我编写了以下蜘蛛

# -*- coding: utf-8 -*-
import scrapy


class QuotesProjectSpider(scrapy.Spider):
     name = 'quotes_project'
     allowed_domains = ['toscrape.com']
     start_urls = ['http://quotes.toscrape.com/random']

    def parse(self, response):
         self.log('i gonna scrape : '+response.url)
         #self.log('the whole page : '+response.text)
         i=1
         tempQuotes = {}
         quotesArray = [ {
            'author' : response.css('div.quote small.author::text')[0].extract(),
            'quote' : response.css('div.quote span.text::text')[0].extract(),
            'tags' : response.css('div.quote div.tags a.tag::text').extract()
        }]
         flag = False
         while i < 100:
              tempQuotes =  {
            'author' : response.css('div.quote small.author::text')[0].extract(),
            'quote' : response.css('div.quote span.text::text')[0].extract(),
            'tags' : response.css('div.quote div.tags a.tag::text').extract()
        }
              flag = False
              j = 0
              n = len(quotesArray)
              while not flag and j < n :
                   if tempQuotes['quote'] == quotesArray[j]['quote'] :
                       flag = True
                   j+=1
              if not flag :
                   quotesArray.append(tempQuotes)
                   i+=1
              print("i = " + str(i))
              print("quote : "+tempQuotes['quote'])
              print("condition : " + str(tempQuotes['quote'] == quotesArray[0]['quote']))

    yield quotesArray

这一行的问题

print("条件:" + str(tempQuotes['quote'] == quotesArray[0]['quote']))

它向我显示了一个无限循环的True,这意味着响应没有更新,因为每次刷新页面时网站都会显示一个新的报价,所以如何在每个循环中更新解析函数的响应。 有人可以帮帮我吗?

【问题讨论】:

    标签: python-3.x web-scraping scrapy


    【解决方案1】:

    您不应该在 parse 方法中处理循环和计数逻辑。 相反,它应该只处理提取您的项目并提出新请求。

    这将提取一个项目,然后重新加载页面。

    def parse(self, response):
        yield {
            'author': response.css('div.quote small.author::text').get(),
            'quote': response.css('div.quote span.text::text').get(),
            'tags': response.css('div.quote div.tags a.tag::text').getall(),
        }
    
        yield response.request
    

    要阻止这种情况永远持续下去,您可以使用Close spider extension
    设置 CLOSESPIDER_ITEMCOUNTCLOSESPIDER_PAGECOUNT 应该适用于您的用例。

    【讨论】:

      【解决方案2】:

      正如 stranac 所指出的,最简单的方法是使用 close spider extension

      你的蜘蛛职责应该只是构建项目和请求。

      您代码中的另一个问题是[0].extract(),您应该改用.extract_first()

      代码如下所示:

      myspider.py

      from scrapy.spiders import Spider
      
      class MySpider(Spider):
      
          name = 'toscrape.com'
      
          start_urls = ['http://quotes.toscrape.com/random']
      
          custom_settings = {
              'CLOSESPIDER_ITEMCOUNT': 100,
          }
      
          visited_quotes = set()
      
          def parse(self, response):
      
              quote = response.css('div.quote span.text::text').extract_first()
      
              if not quote in self.visited_quotes:
                  self.visited_quotes.add(quote)
                  yield {
                      'author' : response.css('div.quote small.author::text').extract_first(),
                      'quote' : quote,
                      'tags' : response.css('div.quote div.tags a.tag::text').extract()
                  }
      
              yield response.request
      

      然后你运行:

      $ scrapy runspider myspider.py -o out.json

      【讨论】:

      • 谢谢@Guillaume,但这并不能解决我的问题,因为这会导致数据冗余,因为网站可以多次显示相同的报价,所以如何测试提取的数据是否在集合中之前提取的?
      • @ekka 您可以简单地使用一组来记住您已经访问/看到的引号,我已经稍微更新了代码
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-25
      • 2017-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      相关资源
      最近更新 更多