2016-07-13 3 views
1

Я пытаюсь собрать данные о домах для продажи в Амстердаме на http://www.funda.nl/koop/amsterdam/. На главной странице отображается только ограниченное количество домов, а в нижней части есть пейджер, который выглядит следующим образом:В Scrapy, как петля над несколькими start_urls, которые сами соскабливаются

enter image description here

(«Volgende» означает «Next» на голландском языке). Из этого я делаю вывод, что всего 255 страниц. На каждой из этих страниц есть URL http://www.funda.nl/koop/amsterdam/p2/, http://www.funda.nl/koop/amsterdam/p3/ и так далее. Чтобы получить данные обо всех домах, я хотел бы «перевернуть» все подстраницы p1, p2, ..., p255.

Я пытаюсь понять, как я могу «установить это». До сих пор я написал следующий код:

import scrapy 
from scrapy.spiders import CrawlSpider, Rule 
from scrapy.linkextractors import LinkExtractor 
from Funda.items import FundaItem 
# from scrapy.shell import inspect_response 

class FundaSpider(CrawlSpider): 
    name = "Funda" 
    allowed_domains = ["funda.nl"] 
    start_urls = ["http://www.funda.nl/koop/amsterdam/"] 

    le1 = LinkExtractor(allow=r'%s+huis-\d{8}' % start_urls[0])  # Link to the page of an individual house, such as http://www.funda.nl/koop/amsterdam/huis-49805292-nieuwendammerdijk-21/ 

    le2 = LinkExtractor(allow=r'%s+p\d+' % start_urls[0]) # Link to a page containing thumbnails of several houses, such as http://www.funda.nl/koop/amsterdam/p10/ 

    rules = (
    Rule(le1, callback='parse_item'), 
    Rule(le2, callback='get_max_page_number') 
    ) 

    def parse_item(self, response): 
     links = self.le1.extract_links(response) 
     for link in links: 
      if link.url.count('/') == 6 and link.url.endswith('/'): 
       item = FundaItem() 
       item['url'] = link.url 
       yield item 

    def get_max_page_number(self, response): 
     links = self.le2.extract_links(response) 
     max_page_number = 0 
     for link in links: 
      if link.url.count('/') == 6 and link.url.endswith('/'): 
       page_number = int(link.url.split("/")[-2].strip('p')) 
       if page_number > max_page_number: 
        max_page_number = page_number 
     return max_page_number 

LinkExtractor le2 перезванивает get_max_page_number, который просто возвращает число 255. Я тогда хотел бы использовать этот номер «синтезировать» другое start_urls для применяться к LinkExtractor le1, который получает ссылки на отдельные дома на каждой странице.

Проблема заключается в том, что, насколько я понимаю, scrapy обрабатывает эти запросы асинхронно, поэтому я не могу гарантировать, что он сначала получит номер 255, а затем будет использовать этот номер для генерации других запросов. Если это так, мне нужно последовательно использовать двух пауков и вызывать их из сценария, а во втором пауке start_url должен быть передан как переменная.

Любые указатели на то, как «установить это»?

ответ

0

Вы здесь слишком усложняете проблему - вам не нужно знать максимальную страницу.

Scrapy имеет url dupefilter, поэтому вы можете использовать linkextractor, чтобы извлекать все видимые страницы каждый раз, и скрипинг будет достаточно умным, чтобы не посещать страницы, на которых он был, если вы не навязываете это.

Так все, что вам нужно здесь два правила с LinkExtractors: Один, который извлекает все ссылки и имеет дозвона parse_item и один, который извлекает все видимые страницы и не имеет обратного вызова или follow=Truesee docs here

+0

Привет Granitosaurus, Я пытаюсь очистить все страницы «p1» до «p255». На главной странице есть только некоторые ссылки: «p1» - «p7» и «p255». Другие ссылки становятся видимыми только после нажатия «Далее». Поэтому я не вижу, как я мог бы очистить все страницы, используя только ссылки на главной странице? –

+0

@hpeek Ваши 'правила' применяются к каждой странице вашего паука. Таким образом, spider извлекает ссылки с каждой страницы, которую он посещает, до тех пор, пока атрибут 'allow' вашего linkextractor позволяет делать это в вашем случае. – Granitosaurus

Смежные вопросы