尝试抓取scrapy中的内部链接内的链接时出现问题?
问题描述:
为了学习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)
尽管如此,它仍然回到我同样的错误输出。有人能帮我澄清这个问题吗?
答
至于我可以看到有两个问题与刮刀:
- 为
parse
被称为在start_urls
每一个元素,你是创建并保存新的数据帧的每一个环节,你是dataframes生成是相互覆盖的。
这就是为什么你会一直在你的crawled_table.csv
解决这个结果只有一个:创建数据框一次,并且推动所有项目都放到同一个数据帧的对象。
然后在每个parse
调用中保存数据帧,以防止刮板在完成前停止。
-
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'技巧,它也没有工作...你能提供一个如何做的例子吗?... –
对不起,我添加了一个代码例如使结构清晰。 – rrschmidt
当我离开'df = pd.DataFrame()'对象离开解析函数时,我得到'NameError:name'df'没有被定义'我把它放在函数中并检出.csv文件及其空。 ..有什么想法做什么? –