尝试使用scrapy抓取访问链接内的链接时出现问题?

时间:2017-04-13 05:05:35

标签: python pandas beautifulsoup scrapy web-crawler

为了学习scrapy,我试图从start_urls列表中抓取一些内部网址。问题是并非urls中的所有元素都有内部NaN(此处我想返回(**))。因此,如何返回以下2列数据框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是数据框,我知道我可以做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) ,但我会做数据框操作。

更新

阅读@rrschmidt后,我试着:

{{1}}

然而,它仍然给我带来了相同的错误输出。有人可以帮我澄清一下这个问题吗?

1 个答案:

答案 0 :(得分:0)

据我所知,你的刮刀存在两个问题:

  1. parse中的每个元素调用start_urls,并且您正在为每个链接创建并保存新的数据帧,您生成的数据帧将相互覆盖。
  2. 这就是为什么你的crawled_table.csv

    中只有一个结果

    解决方案:只创建一次数据帧并将所有项目推送到同一个数据框对象中。

    然后在每个parse调用中保存数据框,以防刮刀在完成之前必须停止。

      如果找不到匹配项,则{li> 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