前言
我们上一篇 “爬取酷狗TOP500(select)” 带领大家初步体验了爬虫的流程,但其中用到的提取方法为 select,此方法提取数据很不健壮,可能过两天对方 html 源码修改,这个爬虫就不能使用了,因为这方法是按照 html 树一层一层元素的选取,当有一个元素修改,树状结构发生变化,就不再可用。
这一节我们使用 find_all 方法提取数据,就如字面意思,找到所有符合的元素,这种方法比 select 更健壮,因为不管 html 树状结构如何改变,此方法都会选择特定的元素而不受 html 树状结构的影响。
此篇教程中 BeautifulSoup 解析器我们会用 lxml
环境配置
前面我们安装了 bs4,requests 库,这次我们再安装一个库 lxml
打开 cmd 命令行(win + r),输入 pip install lxml 完成安装
解析 html
在上一篇中我们是这样解析的:
html = BeautifulSoup(html)
修改成这样:
html = BeautifulSoup(html,'lxml')
BeautifulSoup(response.text,解析器)
第一个参数是请求响应返回的 html 源码;第二个参数是解析器的选择
当然选择器不止 lxml,更多的感兴趣的可自行搜索
选择 lxml 是比较适合的选择,它解析速度快,因为底层是 c 语言封装的,解析准确,所以推荐大家一般情况下使用它
数据提取
# 排名
ranks = html.find_all('span',class_='pc_temp_num')
# 歌手 + 歌名
names = html.find_all('a',class_='pc_temp_songname')
# 播放时间
times = html.find_all('span',class_='pc_temp_time')
把上一篇的 select 方法换成 find_all 方法
find_all(标签名,class_=类名)
第一个参数是标签名,我们来看排名的标签如下:
可以看到它的标签名为 span,class 属性名为 pc_temp_num,所以写为:
# 排名
ranks = html.find_all('span',class_='pc_temp_num')
同理,歌手,歌名,播放时间的如下:
# 歌手 + 歌名
names = html.find_all('a',class_='pc_temp_songname')
# 播放时间
times = html.find_all('span',class_='pc_temp_time')
END
修改的部分已经在上面讲解了,其他的部分不改动
完整代码
import requests
import time
from bs4 import BeautifulSoup
import lxml
def get_html(url):
'''
获得 HTML
'''
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/53\
7.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
else:
return
def get_infos(html):
'''
提取数据
'''
html = BeautifulSoup(html,'lxml')
# 排名
ranks = html.find_all('span',class_='pc_temp_num')
# 歌手 + 歌名
names = html.find_all('a',class_='pc_temp_songname')
# 播放时间
times = html.find_all('span',class_='pc_temp_time')
# 打印信息
for r,n,t in zip(ranks,names,times):
r = r.get_text().replace('\n','').replace('\t','').replace('\r','')
n = n.get_text()
t = t.get_text().replace('\n','').replace('\t','').replace('\r','')
data = {
'排名': r,
'歌名-歌手': n,
'播放时间': t
}
print(data)
def main():
'''
主接口
'''
urls = ['https://www.kugou.com/yy/rank/home/{}-8888.html?from=rank'
.format(str(i)) for i in range(1, 24)]
for url in urls:
html = get_html(url)
get_infos(html)
time.sleep(1)
if __name__ == '__main__':
main()
{'排名': '1', '歌名-歌手': '小阿七 - 那女孩对我说 (正式版)', '播放时间': '4:28'}
{'排名': '2', '歌名-歌手': 'en - 嚣张', '播放时间': '4:14'}
{'排名': '3', '歌名-歌手': '宝石Gem - 野狼disco', '播放时间': '3:59'}
{'排名': '4', '歌名-歌手': '阿悠悠 - 责无旁贷', '播放时间': '3:28'}
。。。。。。