我正在使用Scrapy来抓取业务目录。我有几个领域,我想抓住他们的Facebook和Twitter链接。但是,并非每次都有Facebook或Twitter链接。使用我现在的代码,它只是完全跳过它们。
import scrapy
from scrapy import Request
# TODO: Find a way to scrape even if there is nothing there
# TODO: Find a way to scrape any extra information
class BDSpider(scrapy.Spider):
name = "bd"
start_urls = [
'http://example.url',
]
def parse(self, response):
businesses = response.css('div.card-business')
for business in businesses:
relative_url = business.css('a::attr(href)').extract_first()
absolute_url = response.urljoin(relative_url)
yield Request(absolute_url, callback=self.parse_page, meta={'URL': absolute_url})
def parse_page(self, response):
url = response.meta.get('URL')
# Parse the locations area of the page
locations = response.css('address::text').extract()
# Takes the City and Province and removes unicode and removes whitespace,
# they are still together though.
city_province = locations[1].replace(u'\xa0', u' ').strip()
# List of all social links that the business has
social = response.css('.entry-content > div:nth-child(2) a::attr(href)').extract()
yield {
'title' : response.css('h1.entry-title::text').extract_first().strip(),
'description' : response.css('p.mb-double::text').extract_first(),
'phone_number' : response.css('div.mb-double ul li::text').extract_first().strip(),
'email' : response.css('div.mb-double ul li a::text').extract_first(),
'address' : locations[0].strip(),
'city' : city_province.split(' ', 1)[0].replace(',',''),
'province' : city_province.split(' ', 1)[1].replace(',','').strip(),
'zip_code' : locations[2].strip(),
'website' : social[0],
'facebook' : social[1],
'twitter' : social[2],
'linkedin' : social[3],
'year' : response.css('.list-border > li:nth-child(1)::text').extract_first().strip(),
'employees' : response.css('.list-border > li:nth-child(2)::text').extract_first().strip(),
'key_contact' : response.css('.list-border > li:nth-child(3)::text').extract_first().strip(),
'naics' : response.css('.list-border > li:nth-child(4)::text').extract_first().strip(),
'tags' : response.css('ul.biz-tags li a::text').extract(),
}
我想拥有它,以便如果他们有这些信息然后存储它,但如果没有,那么只留下一个空白字符串。我能做到这一点的最佳方式是什么?
答案 0 :(得分:1)
是否由于social
列表中的social = response.css('.entry-content > div:nth-child(2) a::attr(href)').extract()
try:
facebook = social[0]
except IndexError:
facebook = ''
而跳过它们?如果是这样的话,我会尝试将其拆分为facebook / twitter的单独变量,如下所示:
social = response.css('.entry-content > div:nth-child(2) a::attr(href)').extract()
social = dict(enumerate(social))
facebook = social.get(0, '')
twitter = social.get(1, '')
替代方法:
QList<QDate>
答案 1 :(得分:1)
我将离开Cory Madden的答案,因为它是获得IndexError时我的答案的解决方案。但是,我意识到我使用的代码总是会导致错误。这意味着只有在 100%确定将有内容存在时才使用.extract()
功能。使用商业目录的示例:并非总是100%存在成为一个网站,Facebook或Twitter。所以我做了这个:
我选择了绝对的CSS选择器(右键单击,复制&gt; CSS Selector,如果您使用的是Firefox)并将其粘贴到response.css('')
属性中。所以我的代码看起来像这样:
yield {
# ...code goes here
facebook = response.css('.entry-content > div:nth-child(2) > ul:nth-child(2) > li:nth-child(2) > a:nth-child(1)::attr(href)').extract_first(default=''),
# ...code goes here
}
现在我没有使用try
和except
方法,而是使用extract_first()
方法,您可以传递像default='no data was found'
这样的参数。在我的情况下(我希望它是空白的),我使用了这个:
'facebook' : response.css(css_selector).extract_first(default='')