我正在使用Scrapy,特别是Scrapy的CrawlSpider类来抓取包含某些关键字的Web链接。我有一个很长的start_urls列表,它从连接到Django项目的SQLite数据库获取其条目。我想将抓取的Web链接保存在此数据库中。

我有两种Django模型,一种用于起始URL(例如http://example.com),另一种用于已抓取的Web链接(例如http://example.com/website1http://example.com/website2等)。所有已抓取的Web链接都是start_urls列表中起始URL之一的子站点。

Web链接模型与起始URL模型具有多对一关系,即Web链接模型与起始URL模型具有Foreignkey。为了将我抓取的Web链接正确保存到数据库,我需要告诉CrawlSpiderparse_item()方法,该抓取的Web链接属于哪个开始url。我怎样才能做到这一点? Scrapy的DjangoItem类在这方面无济于事,因为我仍然必须显式定义使用的起始url。

换句话说,如何将当前使用的起始URL传递给parse_item()方法,以便将其与适当的已爬网链接保存到数据库中?有任何想法吗?提前致谢!

最佳答案

默认情况下,您无法访问原始的起始URL。

但是您可以覆盖 make_requests_from_url 方法,并将起始网址放入 meta 中。然后在解析中,您可以从那里提取它(如果您在该parse方法中产生了后续请求,请不要忘记在其中转发该起始网址)。

我没有使用CrawlSpider,也许Maxim建议的内容对您有用,但是请记住,在可能的重定向之后response.url具有url。

这是我将如何执行此操作的示例,但这只是一个示例(摘自教程),未经测试:

class MySpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com']

    rules = (
        # Extract links matching 'category.php' (but not matching 'subsection.php')
        # and follow links from them (since no callback means follow=True by default).
        Rule(SgmlLinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

        # Extract links matching 'item.php' and parse them with the spider's method parse_item
        Rule(SgmlLinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )

    def parse(self, response): # When writing crawl spider rules, avoid using parse as callback, since the CrawlSpider uses the parse method itself to implement its logic. So if you override the parse method, the crawl spider will no longer work.
        for request_or_item in CrawlSpider.parse(self, response):
            if isinstance(request_or_item, Request):
                request_or_item = request_or_item.replace(meta = {'start_url': response.meta['start_url']})
            yield request_or_item

    def make_requests_from_url(self, url):
        """A method that receives a URL and returns a Request object (or a list of Request objects) to scrape.
        This method is used to construct the initial requests in the start_requests() method,
        and is typically used to convert urls to requests.
        """
        return Request(url, dont_filter=True, meta = {'start_url': url})

    def parse_item(self, response):
        self.log('Hi, this is an item page! %s' % response.url)

        hxs = HtmlXPathSelector(response)
        item = Item()
        item['id'] = hxs.select('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
        item['name'] = hxs.select('//td[@id="item_name"]/text()').extract()
        item['description'] = hxs.select('//td[@id="item_description"]/text()').extract()
        item['start_url'] = response.meta['start_url']
        return item

询问您是否有任何问题。顺便说一句,使用PyDev的“转到定义”功能,您可以看到有问题的资源并了解Requestmake_requests_from_url以及其他类和方法需要哪些参数。尽管开始时似乎很困难,但是进入代码有助于并节省您的时间。

10-07 16:05
查看更多