【问题标题】:Problems while trying to crawl links inside visted links with scrapy?尝试使用scrapy抓取已访问链接中的链接时出现问题?
【发布时间】:2017-09-09 01:57:57
【问题描述】:

为了学习scrapy,我正在尝试从start_urls 列表中抓取一些内部网址。问题是并非所有来自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

但它不起作用,知道如何获得(**)

*是一个dataframe,我知道我可以做-o,但是我会做dataframe操作。

更新

阅读@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)

尽管如此,它仍然返回了相同的错误输出。有人可以帮我澄清这个问题吗?

【问题讨论】:

    标签: python pandas beautifulsoup scrapy web-crawler


    【解决方案1】:

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

    1. 因为parsestart_urls 中的每个元素调用,并且您正在为每个链接创建并保存一个新数据框,您正在生成的数据框相互覆盖。

    这就是为什么您的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
    

    【讨论】:

    • 感谢您的帮助。我试图修复缩进以停止覆盖数据框,但显然没有成功。另外,我尝试使用len(l)==0 技巧,但它也没有奏效......你能提供一个如何做到这一点的例子吗?......
    • 对不起,我添加了一个代码示例以使结构清晰。
    • 当我将df = pd.DataFrame() 对象从解析函数中删除时,我得到NameError: name 'df' is not defined 我将它放入函数中并检查了.csv 文件及其空...知道要做什么做什么?
    • 你说得对,因为我将 df 设为类属性时忘记添加 self.。现在它应该可以工作了(只是没有正确的 URL 就无法测试)
    • 是的,df.append 返回一个必须分配回 self.df 的新数据框。修复。请在仍然无法正常工作时发布示例网址,以便我可以进行快速测试。
    猜你喜欢
    • 2016-11-17
    • 1970-01-01
    • 2022-11-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    相关资源
    最近更新 更多