Python 网站上的一个格式破坏者阻止了我的痒蜘蛛
当我的Scrapy Spider遇到网站格式异常值时,它就会停止工作。以下是出错的网站元素(突出显示的部分): 正确的答案具有“a”属性。如下所示((突出显示的部分)): 这是我的蜘蛛:Python 网站上的一个格式破坏者阻止了我的痒蜘蛛,python,web-scraping,scrapy,Python,Web Scraping,Scrapy,当我的Scrapy Spider遇到网站格式异常值时,它就会停止工作。以下是出错的网站元素(突出显示的部分): 正确的答案具有“a”属性。如下所示((突出显示的部分)): 这是我的蜘蛛: import scrapy from scrapy.crawler import CrawlerProcess class MySpider(scrapy.Spider): name = "name" allowed_domains = ["website domain"] start_url
import scrapy
from scrapy.crawler import CrawlerProcess
class MySpider(scrapy.Spider):
name = "name"
allowed_domains = ["website domain"]
start_urls = ['Mywebsite link']
def parse(self, response):
self.log('I just visited: ' + response.url)
for i in response.css('tr.odd'):
item = {
'company_name': i.css('td > a::text')[0].extract(),
'ABN': i.css('td > a::text')[1].extract(),
'status': i.css('td::text')[2].extract(),
'size': i.css('td::text')[3].extract(),
'suburb/town': i.css('td::text')[4].extract(),
'state': i.css('td::text')[5].extract(),
}
yield item
for i in response.css('tr.even'):
item = {
'company_name': i.css('td > a::text')[0].extract(),
**'ABN': i.css('td > a::text')[1].extract()**, # this part stops working
'status': i.css('td::text')[2].extract(),
'size': i.css('td::text')[3].extract(),
'suburb/town': i.css('td::text')[4].extract(),
'state': i.css('td::text')[5].extract(),
}
yield item
# follow pagination link
next_page_url = response.css('li.next > a::attr(href)').extract_first()
if next_page_url:
next_page_url = response.urljoin(next_page_url)
yield scrapy.Request(url=next_page_url, callback=self.parse)
在网站上看起来是这样的:
该行中的“信息不可用”部分阻止了我的爬行器。请告诉我该怎么做。谢谢大家! 让我们一次只关注一个问题: 使用临时变量,而不是直接输出值
for i in response.css('tr.even'):
abn = i.css('td > a::text')[1].extract()
if not abn:
abn = 'Unavailable' # Alternatively, you can use a fallback selector
item = {
'company_name': i.css('td > a::text')[0].extract(),
'ABN': abn,
#...
}
yield item
您可能还需要检查extract()
和extract\u first()
的使用情况。实际上,它推荐使用较新的get()
和getall()
,因为这样比较容易混淆
Scrapy用法文档现在使用.get()和.getall()方法编写。
我们认为,这些新方法的结果是更简洁和可读性
代码
让我们一次只关注一个问题: 使用临时变量,而不是直接输出值
for i in response.css('tr.even'):
abn = i.css('td > a::text')[1].extract()
if not abn:
abn = 'Unavailable' # Alternatively, you can use a fallback selector
item = {
'company_name': i.css('td > a::text')[0].extract(),
'ABN': abn,
#...
}
yield item
您可能还需要检查extract()
和extract\u first()
的使用情况。实际上,它推荐使用较新的get()
和getall()
,因为这样比较容易混淆
Scrapy用法文档现在使用.get()和.getall()方法编写。
我们认为,这些新方法的结果是更简洁和可读性
代码
实现的主要问题是程序可以对不存在的元素调用
extract
方法
for row in response.css('table.views-table tbody tr'):
i = {}
# field specific selectors
i['company_name'], i['ABN'], i['status'], i['size'], i['suburb/town'], i['state'] = row.css('td')
for key in i.keys():
i[key] = i[key].css("*::text").get(default="")
yield i
我使用列表解包来填充项字段(),因为表的每一行都有6列
根据-method
get
return result of first match的说法,这意味着使用此方法,您不需要在表单元格选择器中显式使用
a
标记。实现的主要问题是,您的程序可以对不存在的元素调用extract
方法
for row in response.css('table.views-table tbody tr'):
i = {}
# field specific selectors
i['company_name'], i['ABN'], i['status'], i['size'], i['suburb/town'], i['state'] = row.css('td')
for key in i.keys():
i[key] = i[key].css("*::text").get(default="")
yield i
我使用列表解包来填充项字段(),因为表的每一行都有6列
根据-method
get
return result of first match这意味着使用此方法,您不需要在表单元格选择器中显式使用
a
标记。我通过重写代码解决了此问题。感谢所有的答案贡献者。特别感谢@Gallaecio。以下是我的解决方案:
import scrapy
from scrapy.crawler import CrawlerProcess
class AcncSpider(scrapy.Spider):
name = "spider_name"
allowed_domains = ["url"]
start_urls = ['url']
def parse(self, response):
self.log('I just visited: ' + response.url)
for i in response.css('div.view-content > div > table > tbody > tr.odd'):
item = {
'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(),
'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(),
'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(),
'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(),
'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(),
'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(),
'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first()),
}
yield item
for i in response.css('div.view-content > div > table > tbody > tr.even'):
item = {
'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(),
'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(),
'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(),
'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(),
'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(),
'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(),
'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first())
}
yield item
# follow pagination link
next_page_url = response.css('li.next > a::attr(href)').extract_first()
if next_page_url:
next_page_url = response.urljoin(next_page_url)
yield scrapy.Request(url=next_page_url, callback=self.parse)
我通过重写代码解决了这个问题。感谢所有的答案贡献者。特别感谢@Gallaecio。以下是我的解决方案:
import scrapy
from scrapy.crawler import CrawlerProcess
class AcncSpider(scrapy.Spider):
name = "spider_name"
allowed_domains = ["url"]
start_urls = ['url']
def parse(self, response):
self.log('I just visited: ' + response.url)
for i in response.css('div.view-content > div > table > tbody > tr.odd'):
item = {
'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(),
'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(),
'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(),
'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(),
'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(),
'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(),
'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first()),
}
yield item
for i in response.css('div.view-content > div > table > tbody > tr.even'):
item = {
'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(),
'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(),
'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(),
'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(),
'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(),
'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(),
'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first())
}
yield item
# follow pagination link
next_page_url = response.css('li.next > a::attr(href)').extract_first()
if next_page_url:
next_page_url = response.urljoin(next_page_url)
yield scrapy.Request(url=next_page_url, callback=self.parse)
您的代码在
td
中需要6个链接。输入的HTML应该只有1(而不是公司名称)。考虑从头开始重写你的行提取。谢谢你的回复,但是我不明白你想说什么。你编写了你现在想要修复的代码吗?您了解i.css('td>a::text')[n].extract()在屏幕截图显示输入HTML的情况下所做的工作吗?(注:不鼓励代码截图)url:最上面的代码是实际的网站代码,我的印象是我的循环会抓取td类的文本,并给我法律名称和ABN等信息。您的代码在td
中需要6个链接。输入的HTML应该只有1(而不是公司名称)。考虑从头开始重写你的行提取。谢谢你的回复,但是我不明白你想说什么。你编写了你现在想要修复的代码吗?您了解i.css('td>a::text')[n].extract()在屏幕截图显示输入HTML的情况下所做的工作吗?(注:不鼓励代码截图)url:最上面的代码是实际的网站代码,我的印象是我的循环会抓取td类的文本,并给我诸如合法名称和名称等信息,但是你是在复制原始代码的主要问题,这是滥用[n]
。因此,我应该尝试将tr类用作n,然后提取信息,而不是逐个查看。@Upendra感谢您的回复,但是if not条件仍然会导致错误。不过,您正在用原始代码再现主要问题,这就是误用[n]
。因此,我应该尝试将tr类用作n,然后提取信息,而不是逐个查看。@Upendra感谢您的回复,但是if not条件仍然会导致错误。感谢您的回复,您的代码向我展示了使用Scrapy的一种简洁方法。但是,结果缺少公司名称和ABN。谢谢您的回复,您的代码向我展示了使用Scrapy的简洁方法。然而,结果却丢失了公司名称和ABN。