Как заставить Scrapy очистить соответствующую веб-страницу комментариев после очистки веб-страницы статьи?

#python #scrapy #web-crawler

#python #scrapy #веб-сканер

Вопрос:

Я пытаюсь сканировать новостные статьи и комментарии к ним с помощью scrapy. В моем случае новостные статьи и комментарии к ним находятся на разных веб-страницах, как показано в следующем примере.

(1) Ссылка на статью. http://www.theglobeandmail.com/opinion/editorials/if-britain-leaves-the-eu-will-scotland-leave-britain/article32480429/

(2) Ссылка для комментариев, связанных со статьей. http://www.theglobeandmail.com/opinion/editorials/if-britain-leaves-the-eu-will-scotland-leave-britain/article32480429/comments/

Я хочу, чтобы моя программа понимала, что (1) и (2) связаны. Кроме того, я хочу убедиться, что (2) очищается сразу после (1), а не очищает другие веб-страницы посередине. Я использую следующие правила для очистки веб-страниц новостных статей и веб-страниц комментариев.

 rules = (
         Rule(LinkExtractor(allow = r'/articled /$'),   callback="parse_articles"),
        Rule(LinkExtractor(allow = r'/articled /comments/$'), callback="parse_comments")
)
  

Я попытался использовать явный вызов запроса в функции синтаксического анализа для статей, как показано ниже:

 comments_url = response.url   'comments/'
print('comments url: ', comments_url)
return Request(comments_url, callback=self.parse_comments)
  

Но это не сработало. Как я могу попросить сканер очистить веб-страницу комментариев сразу после очистки веб-страницы статьи?

Ответ №1:

Вам нужно вручную настроить запрос на страницу комментариев.
На каждой странице статьи, которую обнаруживает ваш crawlspider, где-то должен быть URL страницы комментариев, верно?
В этом случае вы можете просто связать запрос страницы обзора в вашем parse_article() методе.

 from scrapy import Request
from scrapy.spiders import CrawlSpider
class MySpider(CrawlSpider):

    rules = (
        Rule(LinkExtractor(allow = r'/articled /$'),   callback="parse_articles"),
    )
    comments_le = LinkExtractor(allow = r'/articled /comments/$')

    def parse_article(self, response):
        item = dict()
        # fill up your item
        ...
        # find comments url
        comments_link  = comments_le.extract_links()[0].link
        if comments_link:
            # yield request and carry over your half-complete item there too
            yield Request(comments_link, self.parse_comments,
                          meta={'item':item})
        else:
            yield item 

    def parse_comments(self, response):
        # retrieve your half-complete item
        item = response.meta['item']
        # add some things to your item
        ...
        yield item
  

Комментарии:

1. Спасибо за ваш ответ! Он переходит по соответствующей ссылке на комментарии, но он по-прежнему не очищает страницу комментариев сразу после страницы статьи. Он очищает другие статьи между ними.

2. @user7009553 да, поскольку scrapy асинхронен, он очищает несколько цепочек параллельно. Таким образом, он может очистить статью и запланировать запрос комментариев, одновременно очищая некоторые другие статьи — однако ваши цепочки не потеряют порядок. Ваша цепочка в данном случае является parse_article-> parse_comments-> yield item, поэтому вы должны получать ожидаемые результаты.