1.是时候来一把实战了
我决定爬取中国皇帝寿命列表,然后存入result.json文件中。好了,开干。
2.爬取
2.1 先找到目标网站
百度百科这个条目下有皇帝寿命列表,好的,就爬这个地址了。
2.2 创建项目
// 创建出项目
scrapy startproject ScrapyPractical
// 进入项目
cd ScrapyPractical/
// 创建出爬虫
scrapy genspider emperor_life_list baike.baidu.com
好了,项目就创建好了。
2.3 进入爬虫文件
进入emperor_life_list.py文件中,可以看到如下内容:
import scrapy
class EmperorLifeListSpider(scrapy.Spider):
name = 'emperor_life_list'
allowed_domains = ['baike.baidu.com']
start_urls = ['http://baike.baidu.com/']
def parse(self, response):
pass
把start_urls修改成寿命列表地址:
start_urls = ['https://baike.baidu.com/item/中国皇帝寿命列表/7344360?fr=aladdin']
2.4 分析网页
通过检查元素,我们能分析出如下界面内容的对应关系。
代码中:
image.png
对应于界面:
image.png
好的,定位到位置,接下来就是分析对应的xpath了。
2.5 分析对应的xpath
tr = response.xpath('//table/tr')
通过这个xpath,我们可以拿到表格的每一行内容。通过分析每一行的数据,可以得到结论,width属性为81的td标签,内容是序号,352是名称,107是岁数,178是在为年份。
tr[0].xpath('.//td[@width=81]/div/text()').get()
'1'
tr[0].xpath('.//td[@width=352]/div/text()').get()
'秦始皇'
tr[0].xpath('.//td[@width=107]/div/text()').get()
'50岁'
tr[0].xpath('.//td[@width=178]/div/text()').get()
'前259年-前210年'
看起来是没问题的,但是仔细观察,会发现名字那一列没有获取全,所以,名字那里应该换一种xpath的写法来获取文字。
tr[0].xpath('string(.//td[@width=352]/div)').get()
'秦始皇嬴政'
好了,拿到全部文字了。
2.6 写代码
代码其实很简单,就不分析了,简单的说就是,先把所有数据提取出来,然后遍历每一条数据,依次取出来,然后yield。
import scrapy
class EmperorLifeListSpider(scrapy.Spider):
name = 'emperor_life_list'
allowed_domains = ['baike.baidu.com']
start_urls = ['https://baike.baidu.com/item/中国皇帝寿命列表/7344360?fr=aladdin']
def parse(self, response):
# 拿到每一行数据
trs = response.xpath('//table/tr')
for tr in trs:
# 分析每一行
name = tr.xpath('string(.//td[@width=352]/div)').get()
if name:
# 年龄
age = tr.xpath('.//td[@width=107]/div/text()').get()
# 年份
year = tr.xpath('.//td[@width=178]/div/text()').get()
yield {
'name': name,
'age': age,
'year': year
}
2.7 运行
// 进入项目中,运行如下命令
scrapy crawl emperor_life_list -o emperor_life_list.json
在项目中,就能看到爬取到的emperor_life_list.json文件了。
image.png
3.注意事项
1.发现请求下来,爬虫程序没有运行?
看看打印中是否出现robots.txt字段,如下:
image.png
只需要将settings.py文件里的ROBOTSTXT_OBEY参数,设为False,不遵循即可。
image.png
2.发现写入的json文件,是\u开头的Unicode编码?
在settings.py文件中加入FEED_EXPORT_ENCODING='UTF8'即可。如下:
image.png
网友评论