2017-04-13 74 views
0

爲了學習scrapy,我試圖抓取start_urls列表中的一些內部URL。問題是,並非所有元素start_urls有內部urls(這裏我想返回NaN)。因此,我怎麼能返回下面的2列數據框(**)嘗試抓取scrapy中的內部鏈接內的鏈接時出現問題?

visited_link, extracted_link 
https://www.example1.com, NaN 
https://www.example2.com, NaN 
https://www.example3.com, https://www.extracted-link3.com 

到目前爲止,我想:

在:

# -*- coding: utf-8 -*- 


class ToySpider(scrapy.Spider): 
    name = "toy_example" 

    allowed_domains = ["www.example.com"] 

    start_urls = ['https:example1.com', 
        'https:example2.com', 
        'https:example3.com'] 


    def parse(self, response): 
     links = response.xpath(".//*[@id='object']//tbody//tr//td//span//a") 

     lis_ = [] 

     for l in links: 
      item = ToyCrawlerItem() 
      item['visited_link'] = response.url 
      item['extracted_link'] = l.xpath('@href').extract_first() 
      yield item 

     lis_.append(item) 
     df = pd.DataFrame(lis_) 

     print('\n\n\n\n\n', df, '\n\n\n\n\n') 

     df.to_csv('/Users/user/Desktop/crawled_table.csv', index=False) 

然而,上面的代碼它返回我:

出:

extracted_link,visited_link 
https://www.extracted-link.com,https://www.example1.com 

我試圖管理與None問題值:

if l == None: 
       item['visited_link'] = 'NaN' 
      else: 
       item['visited_link'] = response.url 

但它不工作,如何讓(**)

*是一個數據幀,我知道我能做到-o任何想法,但我會做數據幀操作。

UPDATE

閱讀@rrschmidt答案之後,我想:

def parse(self, response): 
    links = response.xpath(".//*[@id='object']//tbody//tr//td//span//a[2]") 

    lis_ = [] 

    for l in links: 

     item = ToyItem() 

     if len(l) == 0: 
      item['visited_link'] = 'NaN' 
     else: 
      item['visited_link'] = response.url 

     #item['visited_link'] = response.url 

     item['extracted_link'] = l.xpath('@href').extract_first() 

     yield item 

     print('\n\n\n Aqui:\n\n', item, "\n\n\n") 

    lis_.append(item) 
    df = pd.DataFrame(lis_) 

    print('\n\n\n\n\n', df, '\n\n\n\n\n') 

    df.to_csv('/Users/user/Desktop/crawled_table.csv', index=False) 

儘管如此,它仍然回到我同樣的錯誤輸出。有人能幫我澄清這個問題嗎?

回答

0

至於我可以看到有兩個問題與刮刀:

  1. parse被稱爲在start_urls每一個元素,你是創建並保存新的數據幀的每一個環節,你是dataframes生成是相互覆蓋的。

這就是爲什麼你會一直在你的crawled_table.csv

解決這個結果只有一個:創建數據框一次,並且推動所有項目都放到同一個數據幀的對象。

然後在每個parse調用中保存數據幀,以防止刮板在完成前停止。

  1. if l == None:將不起作用response.xpath如果未找到任何匹配,則返回空列表。這樣做if len(l) == 0:應該做

在這裏要點是我會怎麼構建刮板(代碼沒有測試!)

# -*- coding: utf-8 -*- 

class ToySpider(scrapy.Spider): 
    name = "toy_example" 

    allowed_domains = ["www.example.com"] 

    start_urls = ['https:example1.com', 
        'https:example2.com', 
        'https:example3.com'] 

    df = pd.DataFrame() 

    def parse(self, response): 
     links = response.xpath(".//*[@id='object']//tbody//tr//td//span//a[2]") 
     items = [] 

     if len(links) == 0: 
      item = ToyItem() 
      # build item with visited_link = NaN here 
      item['visited_link'] = response.url 
      item['extracted_link'] = 'NaN' 
      items.append(item) 
     else: 
      for l in links: 
       item = ToyItem() 
       # build the item as you previously did here 
       item['visited_link'] = response.url 
       item['extracted_link'] = l.xpath('@href').extract_first() 
       items.append(item) 

     items_df = pd.DataFrame(items) 
     self.df = self.df.append(items_df, ignore_index=True) 

     print('\n\n\n\n\n', self.df, '\n\n\n\n\n') 
     self.df.to_csv('/Users/user/Desktop/crawled_table.csv', index=False) 

     return items 
+0

感謝您的幫助。我試圖修復縮進以停止覆蓋數據框,但顯然沒有解決。此外,我試圖做'len(l)== 0'技巧,它也沒有工作...你能提供一個如何做的例子嗎?... –

+1

對不起,我添加了一個代碼例如使結構清晰。 – rrschmidt

+0

當我離開'df = pd.DataFrame()'對象離開解析函數時,我得到'NameError:name'df'沒有被定義'我把它放在函數中並檢出.csv文件及其空。 ..有什麼想法做什麼? –