最近参加了一个数据挖掘比赛,所以一边比赛,一边学Python/(ㄒoㄒ)/~~,相比被算法折磨的死去活来,python就很友好了(●'◡'●),学了点基础就直接应用了。废话不多说直接开始。
环境配置
我们用到的是 bs4,requests,lxml这三个库来提取,其中bs4是简称,全称是 BeautifulSoup4.0 库。中文名也叫“美丽的汤”,安装也很简单。 打开 cmd 命令行(win + r),输入 pip install bs4 完成安装。pip是一个通用的 Python 包管理工具。提供了对Python 包的查找、下载、安装、卸载的功能。 其他两个库同理。成功会提示Successfully installed xxx。
构造请求头
我们需要安装Chrome浏览器,进入浏览器 Ctrl+Shift+I 呼出开发者工具。接着打开网址:https://www.kugou.com/yy/rank/home/1-8888.html?from=rank ,找到如图所示的User-Agent
什么是请求头? 别人网页区别是人还是机器访问的一种手段,我们设置请求头为浏览器的请求头,对方就会认为我们是人为的访问,从而不会反爬,当然这只是最简单的一种防反爬的手段,一般我们都会带上,代码如下: 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' 后面代码会用到。
请求访问网页
def get_html(url):
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
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 源码
解析网页
返回了html源码后,我们需要解析网页 html 源码,需要结构化,便于提取数据。
html = BeautifulSoup(html,"lxml") //"lxml"是解析器。
获取数据
选择要提取数据,右键检查。
#rankWrap > div.pc_temp_songlist > ul > li:nth-child(1) > span.pc_temp_num
其中 li:nth-child(1) 需要改成 li,因为 nth-child(1) 是获取 li 标签下的一条数据,我们是要获取这一页的所有排名。 其他数据同理,得到如下代码。
ranks = html.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_num')
name = html.select('#rankWrap > div.pc_temp_songlist > ul > li > a')
time = html.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_tips_r > span')
整合数据
for r,n,t in zip(ranks,name,time):
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 函数,意思是把对应的排名,歌名歌手,播放时间打包,可以这样理解 zip 函数的结果是一个列表 [(排名,歌手歌名,播放时间)。 每一次循环的 r,n,t 一次对应元组中的元素
get_text()
我们提取到的是这个数据所在的标签信息,并不是实际数据,所以需要使用 get_text() 获得实际数据
.replace('\n','').replace('\t','').replace('\r','')
去掉实际数据中多余的字符串,最后把数据打包成字典打印。
End!
大体思路到这里就结束了,很多地方用了Python123的专栏。非常感谢原文的作者!!!
完整代码
#酷狗TOP500
import time
import requests
from bs4 import BeautifulSoup
def get_html(url):
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 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.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_num')
name = html.select('#rankWrap > div.pc_temp_songlist > ul > li > a')
time = html.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_tips_r > span')
for r,n,t in zip(ranks,name,time):
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_':
if __name__ == '__main__':
main()