【问题标题】:Python Scrapy & YieldPython Scrapy & 产量
【发布时间】:2017-04-17 14:16:45
【问题描述】:

我目前正在第一次使用 Scrapy 开发刮板,我也是第一次使用 Yield。我仍在努力解决产量问题。

刮刀:

  • 抓取一页以获取日期列表(解析)
  • 使用这些日期格式化 URL,然后抓取 (parse_page_contents)
  • 在此页面上,它会查找每个列表的 URL 并抓取各个列表 (parse_page_listings)
  • 我想在单个列表中提取所有数据。每个单独的列表上还有 4 个链接,其中包含更多数据。 (parse_individual_listings)

我很难理解如何将 parse_individual_tabs 和 parse_individual_listings 中的 JSON 组合成一个 JSON 字符串。这将是每个单独列表的一个,并将发送到 API。即使只是暂时打印也可以。

    class MySpider(scrapy.Spider):
    name = "myspider"

    start_urls = [
            '',
    ]


    def parse(self, response):
        rows = response.css('table.apas_tbl tr').extract()
        for row in rows[1:]:
            soup = BeautifulSoup(row, 'lxml')
            dates = soup.find_all('input')
            url = ""
            yield scrapy.Request(url, callback=self.parse_page_contents)

    def parse_page_contents(self, response):
        rows = response.xpath('//div[@id="apas_form"]').extract_first()
        soup = BeautifulSoup(rows, 'lxml')
        pages = soup.find(id='apas_form_text')
        urls = []
        urls.append(response.url)
        for link in pages.find_all('a'):
            urls.append('/'.format(link['href']))

        for url in urls:
             yield scrapy.Request(url, callback=self.parse_page_listings)

    def parse_page_listings(self, response):
        rows = response.xpath('//div[@id="apas_form"]').extract_first()
        soup = BeautifulSoup(rows, 'lxml')
        resultTable = soup.find("table", { "class" : "apas_tbl" })

        for row in resultTable.find_all('a'):
            url = ""
            yield scrapy.Request(url, callback=self.parse_individual_listings)


    def parse_individual_listings(self, response): 
        rows = response.xpath('//div[@id="apas_form"]').extract_first() 
        soup = BeautifulSoup(rows, 'lxml')
        fields = soup.find_all('div',{'id':'fieldset_data'})
        for field in fields:
            print field.label.text.strip()
            print field.p.text.strip()

        tabs = response.xpath('//div[@id="tabheader"]').extract_first() 
        soup = BeautifulSoup(tabs, 'lxml')
        links = soup.find_all("a")
       for link in links:
            yield scrapy.Request( urlparse.urljoin(response.url, link['href']), callback=self.parse_individual_tabs)

收件人:

def parse_individual_listings(self, response): 
    rows = response.xpath('//div[@id="apas_form"]').extract_first() 
    soup = BeautifulSoup(rows, 'lxml')
    fields = soup.find_all('div',{'id':'fieldset_data'})
    data = {}
    for field in fields:
        data[field.label.text.strip()] = field.p.text.strip()

    tabs = response.xpath('//div[@id="tabheader"]').extract_first() 
    soup = BeautifulSoup(tabs, 'lxml')
    links = soup.find_all("a")
    for link in links:
        yield scrapy.Request(
            urlparse.urljoin(response.url, link['href']), 
            callback=self.parse_individual_tabs,
            meta={'data': data}
        )
    print data

..

    def parse_individual_tabs(self, response): 
        data = {}
        rows = response.xpath('//div[@id="tabContent"]').extract_first() 
        soup = BeautifulSoup(rows, 'lxml')
        fields = soup.find_all('div',{'id':'fieldset_data'})
        for field in fields:
            data[field.label.text.strip()] = field.p.text.strip()

        print json.dumps(data)

def parse_individual_tabs(self, response): 
        data = {}
        rows = response.xpath('//div[@id="tabContent"]').extract_first() 
        soup = BeautifulSoup(rows, 'lxml')
        fields = soup.find_all('div',{'id':'fieldset_data'})
        for field in fields:
            data[field.label.text.strip()] = field.p.text.strip()

        yield json.dumps(data)

【问题讨论】:

  • 您想生成一个单独的项目来获取您在parse_individual_tabsparse_individual_listings 中的信息吗?
  • 我希望每次调用 parse_individual_listings 时将来自 parse_individual_tabs 的数据和从 parse_individual_listings 打印的所有内容组合成一个 JSON 对象。 (我希望这是有道理的)

标签: python scrapy


【解决方案1】:

通常在获取数据时,您必须使用Scrapy Items,但也可以将它们替换为字典(即您所指的 JSON 对象),因此我们现在将使用它们:

首先,开始在parse_individual_listings 方法中创建项目(或字典),就像在parse_individual_tabs 中创建data 一样。然后将其传递给下一个请求(parse_individual_tabs 将使用 meta 参数捕获该请求,因此它应该如下所示:

def parse_individual_listings(self, response):
    ...
    data = {}
    data[field1] = 'data1'
    data[field1] = 'data2'
    ...
    yield scrapy.Request(
        urlparse.urljoin(response.url, link['href']), 
        callback=self.parse_individual_tabs,
        meta={'data': data};
    )

然后,您可以在parse_individual_tabs 中获取该数据:

def parse_individual_tabs(self, response):
    data = response.meta['data']
    ...
    # keep populating `data`
    yield data

现在parse_individual_tabs 中的data 拥有您想要从两个请求中获得的所有信息,您可以在任何回调请求之间执行相同操作。

【讨论】:

  • 感谢您的建议。是否有可能只是从 parse_individual_listings 调用它并将 JSON 返回到 parse_individual_listings 而不是“屈服”到 parse_individual 选项卡,这样这将具有完整的 JSON?
  • 所以只收集您在parse_individual_listings 中获得的信息?是的,这就是 yield 的好处,你可以从一个方法中得到你想要的时间,所以只需 yield datayield Request(..) 在同一个方法中。
  • 你能再解释一下吗?我试图改变它,但得到错误:Spider must return Request, BaseItem, dict or None, got 'str' now。我将使用我正在使用的新代码更新问题。
  • 如消息所说,直接yielddata,不要转成字符串。
猜你喜欢
  • 1970-01-01
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
  • 2017-08-30
  • 2015-11-14
相关资源
最近更新 更多