我们利用selector方法对酷狗top500进行了爬取,但此方法提取数据很不健壮,当对方对html源码修改进行修改,这个爬虫就不能使用了,因为这方法是按照 html 树一层一层元素的选取,当有一个元素修改,树状结构发生变化,就不再可用。
这里我们使用 find_all 方法提取数据,就如字面意思,找到所有符合的元素,这种方法比 select 更健壮,因为不管 html 树状结构如何改变,此方法都会选择特定的元素而不受 html 树状结构的影响。
Selector方法中我们安装了bs4和requests库,这次我们还需另一个库——lxml。
打开 cmd 命令行(win + r)
输入 pip install lxml 完成lxml库的安装。
在selector中我们运行的代码是:
html = BeautifulSoup(html)
现在我们将代码修改为:
html = BeautifulSoup(html,'lxml')
第一个参数是请求响应返回的 html 源码;第二个参数是解析器的选择,当然选择器不止 lxml,选择 lxml 是比较适合的选择,它解析速度快,因为底层是 c 语言封装的,解析准确,所以推荐大家一般情况下使用它
2.2.3数据提取在selector中我们的提取代码为:
ranks = html.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_num')
names = html.select('#rankWrap > div.pc_temp_songlist > ul > li > a')
times = html.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_tips_r > span')
现在我们将其中的select修改为find_all方法即可
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')
右击元素中检查,我们可以知道元素的对应标签和类名,也就是我们的第一个参数和第二个参数,find_all(标签名,class_=类名)
我们来看看排名的标签如下:
可以看到它的标签名为span,class属性名为pc_temp_num,所以写为:ranks = html.find_all('span',class_='pc_temp_num')
修改的部分在上面已经进行讲解,其余的部分和selector中不做改动
代码如下:
import requests
import time
from bs4 import BeautifulSoup
import lxml
def get_html(url):
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()
运行效果如下: