2017-04-13 72 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文件及其空。 ..有什么想法做什么? –