【问题标题】:scrapy general parse workflowscrapy 通用解析工作流程
【发布时间】:2016-03-09 23:50:27
【问题描述】:

我是 python 和 scrapy 的新手,希望了解其中的方法。 我已经尝试过有关scrapy的官方教程并遵循它,但这只是一个基本示例。我下面描述的要求有所不同,只是稍微复杂一点。

有一个网站显示来自数据库的项目。
对于每个项目,我需要从每个单独的项目页面和搜索结果(列表)页面获取属性。 搜索结果页面 URL 的格式为:

    http://example.com/search?&start_index=0

更改 start_index 将更改结果的起始位置。 每个结果页面仅显示 10 条记录。

结果以如下格式显示在表格单元格中:

    link | Desc. | Status

我需要检索 Desc。和 Status 属性,然后点击链接到包含更多详细信息的页面,我还将为 Item 检索这些详细信息。
我希望从任何起始索引中检索给定数量的记录。 我目前使用scrapy的方法如下所示(为简洁起见进行了编辑):

import scrapy

from scrapy.exceptions import CloseSpider
from cbury_scrapy.items import MyItem

class ExampleSpider(scrapy.Spider):
    name = "example"
    allowed_domains = ["example.com"]
    start_urls = [
        "http://example.com/cgi/search?&start_index=",
    ]

    url_index = 0
    URLS_PER_PAGE = 10
    records_remaining = 16
    crawl_done = False

    da = MyItem()        

    def parse(self, response):
        while self.crawl_done != True:
            url = "http://example.com/cgi/search?&start_index=" + str(self.url_index)
            yield scrapy.Request(url, callback=self.parse_results)
            self.url_index += self.URLS_PER_PAGE


    def parse_results(self, response):
        # Retrieve all table rows from results page
        for row in response.xpath('//table/tr[@class="datrack_resultrow_odd" or @class="datrack_resultrow_even"]'):
            # extract the Description and Status fields

            # extract the link to Item page
            url = r.xpath('//td[@class="datrack_danumber_cell"]//@href').extract_first()
            yield scrapy.Request(url, callback=self.parse_item)

            if self.records_remaining == 0:
                self.crawl_done = True
                raise CloseSpider('Finished scrape of requested number of records.')

            self.records_remaining -= 1

    def parse_item(self, response):
        # get fields from item page
        # ...   
        yield self.item

records_remaining 达到 0 甚至在抛出 CloseSpider 异常之后代码当前不会停止,这是一个错误。

我觉得这源于解析方法的排列方式错误。 以“scrapy”方式构建它的正确方法是什么? 任何帮助表示赞赏。

【问题讨论】:

    标签: python scrapy workflow yield


    【解决方案1】:
    def parse(self, response):
        list_of_indexes = response.xpath('place xpath here that leads to a list of urls for indexes')
        for indexes in list_of_indexes:    
            #maybe the urls are only tags ie. ['/extension/for/index1', '/extension/for/index2', etc...]
            index_urls = ['http://domain.com' + index for index in indexes]
            yield scrapy.Request(index_urls, callback = self.parse_indexes)
    
    def parse_index(self, response):
        da = MyItem()
        da['record_date'] = response.xpath('xpath_here')
        da['record_summary'] = response.xpath('xpath_here')
        da['additional_record_info'] = response.xpath('xpath_here')
        yield da
    

    这个例子过于简单了,但我希望它有所帮助。

    您想在解析本身中实例化您的项目da = MyItem()

    要回答有关解析流程的更大问题,我将从 URL 开始。从 start_url 找到索引的 XPath 后,您将使用

    scrapy.Requests(URL = index_url, callback =parse_indexes)
    

    这会将您的蜘蛛引导到下一个解析方法 parse_indexes。

    index_url 将通过必要的 xpath 从迭代中提取。

    parse_indexes 就像 parse 一样,但会从 the_next_index_url 中提取信息

    如果这个答案是正确的,我可以稍后发布一个示例。

    【讨论】:

    • 您好 Liam,我将 da 项作为 ExampleSpider 的成员,因此蜘蛛的所有解析方法都可以访问它。您是否建议我将 da 传递给每个解析方法?我将您的回答解释为建议收集所有 URL,然后在单独的解析中跟踪它们,这可能是一个好方法。我想看一个例子,因为我仍然不清楚正确的做法。谢谢!
    • 是的,完全正确。我在答案中添加了一个示例。希望对你有帮助!
    • 感谢 Liam 的示例,我应该澄清一下,对 da 项目的抓取从搜索结果页面开始,因为提供的字段(描述和状态)仅出现在搜索结果页面的每一行中(而不是不幸的是,在每个单独的记录页面内)。因此,我在第一遍看到 da 实例化,收集链接 Desc。和状态。然后第二遍可以跟随链接并请求单个项目页面,填充剩余的字段。
    • 我在这里找到了在解析方法之间传递数据的scrapy方式:doc.scrapy.org/en/latest/topics/…
    猜你喜欢
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2015-05-01
    • 1970-01-01
    相关资源
    最近更新 更多