#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, поэтому вы должны получать ожидаемые результаты.