通过上期的分享,我们得到了第一个网页的所有小说的名字,通过查看网页可以发现,单击小说名字后,就进入了小说详细界面,上面有小说的名字,作者,种类等信息,那我们如何爬取这些信息,这就是本期分享的内容(解析多层或者说下一层网页)。
1. scrapy spider解析多层网页
我们在解析小说名字的时候,查看底层代码可以看到一个a标签,此a标签就是下层网页的URL地址,我们在解析小说名字的代码基础上,增加如下代码:
novelname = td.find('a').get_text()#小说名字
novelurl = td.find('a')['href']#小说地址
有了小说地址,如何解析这一层的网页,我们新建一个函数get_information来解析,在构造get_information函数前,我们先把小说地址给到调度器,使用request来返回URL的内容:
yield Request(novelurl, callback=self.get_information, meta={'name': novelname, 'url': novelurl})
此句代码的意思是request请求novelurl网页,返回的数据有get_information函数来解析里面我们需要的Item,把已经解析到的novelname与novelurl带入get_information函数,以便存入item中.
1.1 yield函数:
带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代,简要理解yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。
1.2 get_information函数
def get_information(self,response):
#解析网页
soupItems = BeautifulSoup(response.text, 'lxml')
#获取小说种类
category = soupItems.find('table').find('a').get_text()
#获取小说作者
author = str(soupItems.find('table').find_all('td')[1].get_text()).replace('\\xa0', '')
#获取小说目前状态
status = str(soupItems.find('table').find_all('td')[2].get_text()).replace('\\xa0', '')
#获取小说字数
num = str(soupItems.find('table').find_all('td')[4].get_text()).replace('\\xa0', '')
当解析完所有的Item后,传入我们要存的Item中,但在此前,需要在我们spider工程Items中添加需要存入的Item
1.3 Items
class PowersItem(scrapy.Item):
novelname = scrapy.Field()#小说名字
author = scrapy.Field() # 作者
category = scrapy.Field() # 类别
novelurl=scrapy.Field()#小说地址
status=scrapy.Field()#状态
num=scrapy.Field()#字数
pass
1.4 保存Items
item = PowersItem()
item['novelname'] = response.meta['name']#从上一个函数传入的名字
item['author'] = author
item['category'] = category
item['status'] = status
item['num'] = num
item['novelurl'] = response.meta['url']#从上一个函数传入的地址
yield item
spider
输出>>>
{'author': '若木扶苏',
'category': '女频频道',
'novelname': '凶悍小王妃',
'novelurl': 'https://www.23us.so/xiaoshuo/28112.html',
'num': '1624979字',
'status': '完本'}#其它略
完整代码如下:
def parse(self , response):
tds = BeautifulSoup(response.text, 'lxml').find_all('tr', bgcolor='#FFFFFF')
for td in tds:
novelname = td.find('a').get_text()
novelurl = td.find('a')['href']
yield Request(novelurl, callback=self.get_information, meta={'name': novelname, 'url': novelurl})
def get_information(self,response):
#参考以上代码
本期代码在上期的代码基础上改编,由于篇幅的限制,大家可以参考往期的文章,编写自己的spider来做练习。
下期预告
我们已经得到了所有的Items,但是程序并没有保存Items,下期介绍MySql数据库,来如何保存我们的Items。