第一步:下载谷歌浏览器
第二步:安装bs4,requests库
打开 cmd 命令行(win + r)
输入 pip install bs4 完成bs4模块安装。
输入 pip install requests 完成requests模块安装。
如果执行 pip install bs4 后报错为“pip 不是可执行的命令”,将pip 的路径加入环境变量即可
2.1.3 构造请求网址提供URL如下:
https://www.kugou.com/yy/rank/home/1-8888.html?from=rank
我们观察 url 如下几个字段:
https:超文本传输协议
www.kugou.com:域名
yy/rank/home/1-8888:域名下的子网页
.html:代表此网页是静态的,后面会讲
?:问好后面的一般都是一些请求参数
打开后只能看到前 22 名的数据,如下:
我们可以看到,其中有一个 1-8888 这个参数,打开上述网址后我们只能看到前 22 首歌,如果需要查看更多内容可以下载客户端,但是这里我们把 1-8888 改成 2-8888其实也是可以实现翻页的效果,如下:
我们可以根据排名共有500条记录可以知道一共有23页:
到这里我们我们需要提取的数据就知道在哪里了。
在知道了有多少页以及 url 的含义后,通过以下代码构造所有的 url:
urls = ['https://www.kugou.com/yy/rank/home/{}-8888.html?from=rank'.format(str(i)) for i in range(1, 24)]
我们需要的所有url就都包含在urls中了
2.1.4构造请求头一般浏览器都会有反爬机制,用来区别是人还是机器访问的一种手段。我们设置请求头为浏览器的请求头,以模拟成人为的访问,当然这只是最简单的一种防反爬的手段,一般我们都会带上,代码如下:
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'}
这个headers是先通过人为访问,在headers中的user-agent找到:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
else:
return
response = requests.get(url, headers=headers)
使用 requests 库的get方法访问网页,第一个参数为网址,第二个参数为请求头,返回值里面有很多结果,包括有状态响应码,网页源码,二进制等,赋值给我们定义的response
response.status_code == 200
调用请求结果 response 中的status_code查看请求状态码,200代表请求成功,就返回,否则返回一个 None,状态码一般有 2xx,4xx,3xx,5xx,分别代表请求成功,客户端访问失败,重定向,服务器问题。
return response.text表示返回响应结果的text,即网页html源码
在请求访问网页中我们得到了我们需要的response,其中的html源码也被我们所得到,但是这个源码比较丑陋,所以我们可以利用beautifulsoup来对源码进行煲汤。
html = BeautifulSoup(html)
2.1.7 提取数据
在浏览器中将鼠标指向我们所需要提取的元素,右击检查后会出现对应源码,右击→copy→copy 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')
2.1.8 获得数据
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','')
用zip 函数,把对应的排名,歌名歌手,播放时间打包,打包结果为一个列表,[(排名,歌手歌名,播放时间),(排名,歌手歌名,播放时间),……]
使用 get_text() 获得实际数据
这种提取方式是不会常用的,因为效果很不健壮,如果网页改了改结构,就不能使用了。
代码如下:
import requests
import time
from bs4 import BeautifulSoup
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)
# 排名
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')
# 打印信息
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()
运行效果如下: