import requests
from bs4 import BeautifulSoup
其中request模块用来获取网页的html数据,BeautifulSoup用于解析获取到的html数据
我们通常用request.get("网址")的方法来获得一个网站的html数据,但是由于许多网站的反爬机制,我们可以把自己伪装成一个浏览器,具体操作如下:
以这次的网站音乐排行榜为例,我们在进入该网站之后按键盘上的F12就可以进入开发者工具
edge浏览器操作如下
其余浏览器打开“Network”
按F5刷新
在左栏选中第一个,然后右侧窗口拉到底就复制得到浏览器的User-Agent
headers={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183"
}
新建一个字典headers然后把刚刚复制的内容作为值存放到里面,相应键的名称为“User-Agent”
response = requests.get("https://y.qq.com/n/ryqq/toplist/26",headers = headers)
然后我们在括号内添加上headers=headers
print(response.text)
以text的形式把response打印出来,可以判断是否成功获取到
如果打印出了一大串这样的东西说明成功获取到 html数据了!
html = response.text
soup = BeautifulSoup(html,"html.parser")
info = []
首先我们将得到的内容作为字符串存放到html这个变量中
然后把这个内容传入BeautifulSoup的构造函数里,并添加上解析器"html.parser",然后把这个对象赋值为soup
列表info用于存储之后解析出的数据
将鼠标放到网页上相应的元素上就能在开发者工具页面显示相应的html代码
我们把鼠标放在任意一个歌手名上会看到窗口展示了这样的代码
在观察每一个含歌手名的代码后,会发现所有的歌手名都包含在了 用findAll函数找到相应的元素,第一个参数传入“div”表示找到所有 循环打印即可得到下面内容 可以看到所有包含歌手名的元素被打印了出来,但是我们只想要歌手名,不要其他字符 在循环里,通过find()函数我们找到全部的标签,然后赋值给name_link此时的name_link应该是如下内容 这时我们用name_link.string就能直接读取到我们想要的内容了,然后存入info中 但是!通过观察发现,既然歌手名都包含在了标签内那么为什么不直接查找标签呢? 其实是可行的。 修改findAll里的参数,我们直接获取到了全部的a标签,然后再在循环中用get函数即可直接获取到全部的歌手名。 从以上的两个获取歌手名的方式我们了解到了findAll函数可以获取到对应的标签,而get函数可以进一步获取到标签内的特定信息。通过我们对html数据的观察可以发现,一首歌如果有多个歌手,那么这几个歌手将会被保存在同一个 方法与上面类似,我们对所有歌名和专辑名进行分析 发现他们都存在标签内,而且class属性都为songlist__songname__txt 于是我们可以写出下面的代码 然后把获取的内容存到info里 在这次获取时,我用了一个不一样的办法,因为在拿到标签里的内容后仍然存在很多我们不想要的信息 但观察后发现所有歌名和专辑名前面都有"title=",所以我们可以使用列表推导式从每个标签中提取title属性,并将结果存储在列表info中。 到这里为止我们已经解析到了全部的内容 由于提供的榜单有很多,但是这个代码只能获取到其中的一种榜单,实用性不高 我们点开不同的榜单观察他们的url 每个榜单的URL有区别的地方只在于最后的数字所以可以对之前获取html数据的代码进行修改 新创建一个变量num用于存放数字,然后用f字符串把他放在URL的最后代替掉固定的数字 然后我们把允许用户查询的榜单和对应的URL最后的数字存放在字典top中,然后写一些便于用户输入的代码以及最终输出榜单内容的代码,就完成了! 附上源码:all_names = soup.findAll("div",attrs={"class":"songlist__artist"})#提取全部含有歌手名的元素
for names in all_names:
print(names)
for names in all_names:#往info添加歌手名信息
name_link = names.find("a")
info.append([name_link.string])
all_names = soup.findAll("a",attrs={"class":"playlist__author"})#提取全部含有歌手名的元素
for names in all_names:#往info添加歌手名信息
name_link = names.get("title")
处理多个歌手的情况
all_names = soup.findAll("div",attrs={"class":"songlist__artist"})#提取全部含有歌手名的元素
for names in all_names:#往info添加歌手名信息
name_link = names.findAll("a")#找到同一首歌里的全部歌手
info.append([[i.get("title") for i in name_link]])#将同一首歌的歌手放在同一个列表中再将他们放入info中
获取所有歌名和专辑名
all_songs = soup.findAll("span",attrs={"class":"songlist__songname_txt"})
idx = 0#记录当前遍历到列表的索引号
for songs in all_songs:#往info添加歌名以及专辑名信息
song_link = songs.findAll("a")
for t in song_link:
info[idx].append(t["title"])
idx += 1
为代码增加实用性
response = requests.get(f"https://y.qq.com/n/ryqq/toplist/{num}",headers = headers)
import requests
from bs4 import BeautifulSoup
top = {62:"飙升榜",26:"热歌榜",27:"新歌榜",4:"流行指数榜",5:"内地榜",3:"欧美榜",16:"韩国榜",17:"日本榜",105:"日本公信榜",28:"网络歌曲榜",
63:"DJ舞曲榜",60:"抖音快手榜",128:"YouTube榜",57:"电音榜",65:"国风榜",58:"说唱榜",72:"动漫音乐榜",73:"游戏音乐榜"}
print(top)
while True:
num = int(input("请输入你要查看的榜单号码:"))
if num not in top:
print("无该榜单,请重新输入!")
else:
break
#获取html数据
headers={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183"
}
response = requests.get(f"https://y.qq.com/n/ryqq/toplist/{num}",headers = headers)
html = response.text
soup = BeautifulSoup(html,"html.parser")
info = []#存放提取到的信息
all_songs = soup.findAll("span",attrs={"class":"songlist__songname_txt"})#提取全部含有歌名以及专辑名的元素
all_names = soup.findAll("div",attrs={"class":"songlist__artist"})#提取全部含有歌手名的元素
for names in all_names:#往info添加歌手名信息
name_link = names.findAll("a")
info.append([[i.get("title") for i in name_link]])
idx = 0#记录当前遍历到列表的索引号
for songs in all_songs:#往info添加歌名以及专辑名信息
song_link = songs.findAll("a")
for t in song_link:
info[idx].append(t["title"])
idx += 1
print(top[num])
for i in range(len(info)):#输出info中的信息
print(f"{i+1} 歌手:{'/'.join(info[i][0])}\n\t歌曲:《{info[i][2]}》\n\t专辑:《{info[1][1]}》")