在发送用于scrapy的提取之前修改URL

时间:2014-10-13 13:21:19

标签: python scrapy scrapy-spider

我想解析站点地图并找到站点地图中的所有网址,然后在所有网址上附加一些单词,然后我想查看所有修改网址的响应代码。

对于此任务,我决定使用scrapy,因为它可以抓取站点地图。它在scarpy的documentation

中给出

在本文档的帮助下,我创建了我的蜘蛛。但我想在发送之前更改网址。所以为此,我试图从this link获得帮助。此链接建议我使用rules并实施process_requests()。但我无法利用这些。我累了一点,我评论过。任何人都可以帮我写注释行的确切代码或在scrapy中执行此任务的任何其他方法吗?

from scrapy.contrib.spiders import SitemapSpider
class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.example.com/sitemap.xml']
    #sitemap_rules = [some_rules, process_request='process_request')]

    #def process_request(self, request, spider):
    #   modified_url=orginal_url_from_sitemap + 'myword'
    #   return request.replace(url = modified_url)        

    def parse(self, response):
        print response.status, response.url  

3 个答案:

答案 0 :(得分:1)

您可以将request_scheduled信号附加到函数,并在函数中执行您想要的操作。例如

class MySpider(SitemapSpider):

    @classmethod
    def from_crawler(cls, crawler):
        spider = cls()
        crawler.signals.connect(spider.request_scheduled, signals.request_scheduled)

    def request_scheduled(self, request, spider):
        modified_url = orginal_url_from_sitemap + 'myword'
        request.url = modified_url

答案 1 :(得分:0)

我只是面对这个。显然,您不能真正使用process_requests,因为SitemapSpider中的站点地图规则与Rule中的CrawlSpider对象不同-只有后者可以具有此参数。

检查the code后,似乎可以通过手动覆盖SitemapSpider实现的一部分来避免这种情况:

class MySpider(SitemapSpider):
    sitemap_urls = ['...']
    sitemap_rules = [('/', 'parse')]

    def start_requests(self):
        # override to call custom_parse_sitemap instead of _parse_sitemap
        for url in self.sitemap_urls:
            yield Request(url, self.custom_parse_sitemap)

    def custom_parse_sitemap(self, response):
        # modify requests marked to be called with parse callback
        for request in super()._parse_sitemap(response):
            if request.callback == self.parse:
                yield self.modify_request(request)
            else:
                yield request

    def modify_request(self, request):
        return request.replace(
            # ...
        )

    def parse(self, response):
        # ...

答案 2 :(得分:0)

SitemapSpider具有sitemap_filter method.
您可以覆盖它以实现所需的功能。

class MySpider(SitemapSpider):

    ...
        def sitemap_filter(self, entries):

            for entry in entries:
                entry["loc"] = entry["loc"] + myword
                yield entry

每个entry对象都是具有以下结构的字典:

<class 'dict'>:
 {'loc': 'https://example.com/',
  'lastmod': '2019-01-04T08:09:23+00:00',
  'changefreq': 'weekly',
  'priority': '0.8'}

重要提示!SitemapSpider.sitemap_filter方法出现在2019年1月发布的scrapy 1.6.0 1.6.0 release notes - new extensibility features section