python
  • scrapy
  • yield
  • 2013-08-07 6 views 1 likes 
    1

    возникли проблемы со следующим простым кодом скребущего сайта Форума Справки:SCRAPY сломана

    class ForumSpider(CrawlSpider): 
        ... 
    
        rules = (
          Rule(SgmlLinkExtractor(restrict_xpaths="//div[@class='threadlink condensed']"), 
          callback='parse_threads'), 
          ) 
    
        def parse_threads(self, response): 
    
         thread = HtmlXPathSelector(response) 
    
         # get the list of posts 
         posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/*") 
    
         # plist = [] 
         for p in posts: 
          table = ThreadItem() 
    
          table['thread_id'] = (p.select("//input[@name='searchthreadid']/@value").extract())[0].strip() 
    
          string_id = p.select("../@id").extract() # returns a list 
          p_id = string_id[0].split("post") 
          table['post_id'] = p_id[1] 
    
          # plist.append(table) 
          # return plist 
          yield table 
    

    Некоторых XPATH hackiness в стороне, когда я запускаю это с выходом Я получаю очень странные результаты с несколькими хитами те же thread_id и post_id. Что-то вроде:

    114763,1314728 
    114763,1314728 
    114763,1314728 
    114763,1314740 
    114763,1314740 
    114763,1314740 
    

    Когда я переключаюсь обратно в ту же логику с возврата (в комментариях) все работает отлично. Я думаю, что это может быть некоторая основная ошибка с генератором, но я не могу понять это. Почему одни и те же должности попадают несколько раз? Почему код работает с использованием return, но не Доход?

    Полный фрагмент кода в сущности here.

    ответ

    1

    Похоже, что это проблема с отступом. Следующие должны работать так же, как с помощью списка и возврата:

    def parse_threads(self, response): 
    
        thread = HtmlXPathSelector(response) 
    
        # get the list of posts 
        posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/*") 
    
        for p in posts: 
         table = ThreadItem() 
    
         table['thread_id'] = (p.select("//input[@name='searchthreadid']/@value").extract())[0].strip() 
    
         string_id = p.select("../@id").extract() # returns a list 
         p_id = string_id[0].split("post") 
         table['post_id'] = p_id[1] 
    
         yield table 
    

    UPD: Я исправил и улучшил код вашего метода parse_threads, должно работать:

    def parse_threads(self, response): 
        thread = HtmlXPathSelector(response) 
        thread_id = thread.select("//input[@name='searchthreadid']/@value").extract()[0].strip() 
        post_id = thread.select("//div[@id='posts']//table[contains(@id,'post')]/@id").extract()[0].split("post")[1] 
    
        # get the list of posts 
        posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/tr[2]") 
        for p in posts: 
         # getting user_name 
         user_name = p.select(".//a[@class='bigusername']/text()").extract()[0].strip() 
    
         # skip adverts 
         if 'Advertisement' in user_name: 
          continue 
    
         table = ThreadItem() 
         table['user_name'] = user_name 
         table['thread_id'] = thread_id 
         table['post_id'] = p.select("../@id").extract()[0].split("post")[1] 
    
         yield table 
    

    Надежда, что помогает.

    +0

    О, мои извинения! Отступ правилен в текущем коде. Это была просто ошибка копирования и вставки. – denten

    +0

    Ну, тогда это должно сработать ... не видно никаких ошибок. Не могли бы вы показать весь код вашего паука, чтобы я мог воспроизвести его? – alecxe

    +0

    https://gist.github.com/denten/d898a48bcf2a496c7c07 – denten

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