爬取网易云音乐所有歌单信息

本文介绍了一种使用Python、requests、lxml和selenium爬取网易音乐歌单的详细方法,包括获取分类URL、解析歌单信息及存储数据。
部署运行你感兴趣的模型镜像

可以结合下一篇文章实现歌曲下载
python 爬虫下载网易歌单歌曲

使用 python + requests + lxml + selenium

  1. 使用 requests 发起请求,获取到所有分类的 url
  2. 使用 selenium 发送请求取到每页的每个歌单信息
  3. 点击下一页,爬取下一页的歌单信息
  4. 存储信息
import requests, time
from selenium import webdriver
from lxml import etree
from requests.utils import unquote
from selenium.webdriver.common.keys import Keys


class WangyiMusic:
    def __init__(self):
        self.start_url = "https://music.163.com/discover/playlist/"
        self.url_temp = "https://music.163.com"
        self.headers = {
            "Referer": "https://music.163.com/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3608.4 Safari/537.36"
        }
        self.session = requests.Session()
        self.driver = webdriver.Chrome()

    def parse_get_url(self):
        resp = self.session.get(self.start_url, headers=self.headers)
        return resp.content.decode()

    def get_category_list(self, html_str):
        el = etree.HTML(html_str)
        dl_list = el.xpath("//div[@class='bd']/dl")
        category_list = []
        for dl in dl_list:
            a_list = dl.xpath(".//a[@class='s-fc1 ']")
            for a in a_list:
                items = {}
                items["cate_name"] = a.xpath("./text()")[0]
                items["cate_url"] = self.url_temp + a.xpath("./@href")[0]
                print(items)
                category_list.append(items)

        cate_url_list = [category["cate_url"] for category in category_list]
        print(cate_url_list)
        return category_list, cate_url_list

    def save_category_list(self, category_list):
        pass

    def get_playlist_list(self):
        li_list = self.driver.find_elements_by_xpath("//ul[@id='m-pl-container']/li")
        playlist_list = []
        for li in li_list:
            items = {}
            items["playlist_name"] = li.find_element_by_xpath(".//a[@class='tit f-thide s-fc0']").text
            items["playlist_url"] = li.find_element_by_xpath(".//a[@class='tit f-thide s-fc0']").get_attribute("href")
            items["playlist_author"] = li.find_element_by_xpath(".//a[@class='nm nm-icn f-thide s-fc3']").text
            items["playlist_num"] = li.find_element_by_xpath(".//span[@class='nb']").text
            print(items)
            playlist_list.append(items)

        next_url = self.driver.find_elements_by_xpath(".//a[@class='zbtn znxt']")
        # next_url = self.driver.find_elements_by_link_text("下一页")
        next_url = next_url[0] if len(next_url) > 0 else None
        print(next_url)
        return playlist_list, next_url

    def save_playlist_list(self, playlist_list):
        for playlist in playlist_list:
            with open("music_163.txt", 'a', encoding="utf-8") as f:
                f.write(
                    "歌单名:" + playlist["playlist_name"] + " | | " + "歌单作者: " + playlist[
                        "playlist_author"] + " | | " + "歌单播放量:" + playlist["playlist_num"] + " | | " + "歌单地址:" +
                    playlist["playlist_url"])
                f.write("\n\n")

    def run(self):
        # 先取到所有分类的名称和 url
        # 发起请求
        html_str = self.parse_get_url()
        # 提取分类名和 url 数据
        category_list, cate_url_list = self.get_category_list(html_str)
        # 保存分类名和 url 数据
        self.save_category_list(category_list)

        # 遍历请求每个分类 url,取到分类中的歌单名称与 url
        for cate_url in cate_url_list:
            # 请求每个分类 url
            self.driver.get(cate_url)
            # 进入到 iframe 框架中
            self.driver.switch_to.frame(self.driver.find_elements_by_tag_name("iframe")[0])
            # 设置等待时间
            time.sleep(5)
            # 取到数据
            print("*" * 100)
            print(unquote(self.driver.current_url))  # 输出当前 url

            playlist_list, next_url = self.get_playlist_list()  # 取到第一页的歌单数据
            # 保存数据
            self.save_playlist_list(playlist_list)
            # 请求下一页
            while next_url is not None:
                next_url.send_keys(Keys.ENTER)  # 元素被覆盖,无法点击  用Enter代替click
                time.sleep(5)
                # 提取数据
                playlist_list, next_url = self.get_playlist_list()
                # 保存数据
                self.save_playlist_list(playlist_list)

            print("*" * 100)

        self.driver.quit()


if __name__ == '__main__':
    wangyimusic = WangyiMusic()
    wangyimusic.run()



效果

在这里插入图片描述



中间遇到的问题

selenium 获取到了下一页的元素信息,但是点击失败

原因:元素被覆盖,无法点击

解决:

用Enter代替click

导入from selenium.webdriver.common.keys import Keys

next_url.send_keys(Keys.ENTER) # 元素被覆盖,无法点击 用Enter代替click

发现用Enter代替click后,如果不是下拉加载的页面的话,不用下拉滚动条就能用enter点到

也有其他的解决办法:

手动将页面拉到最下面、

使用加载页面的方法等。

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

### 使用 Python 爬虫抓取网易云音乐歌手歌单数据 为了实现这一目标,可以采用如下方法: #### 准备工作 确保安装必要的库来支持网络请求和解析 HTML 文档。通常会使用 `requests` 库来进行 HTTP 请求操作,并利用 `BeautifulSoup` 或者 `lxml` 来处理页面内容。 ```bash pip install requests beautifulsoup4 lxml ``` #### 获取登录状态下的网页源码 由于部分资源可能仅限于登录用户访问,因此需要模拟浏览器行为完成自动登录过程[^4]。这一步骤对于获取完整的歌曲列表至关重要,因为未登录状态下某些 API 接口返回的数据量有限制。 #### 构建 URL 和发送 GET 请求 构建用于查询特定艺术家作品集的 URL 地址模式,例如 `/artist/album?id=ARTIST_ID` ,其中 ARTIST_ID 是具体的艺人编号。接着向该链接发起 GET 请求以取得响应体中的 JSON 数据结构或其他形式的内容。 #### 解析 JSON 响应提取所需字段 当接收到服务器端传回的信息后,需对其进行分析以便定位到感兴趣的部分——即各个专辑内的曲目详情。一般情况下,这些资料会被封装在一个数组里,每个元素代表一首独立的作品,包含名称、演唱者姓名以及播放地址等属性。 #### 创建本地存储目录保存文件 按照一定规则组织好要储存的目标路径,比如依据艺人的名字建立子文件夹存放其全部录音制品;同时也要考虑到异常情况的发生,像遇到空白标题时则默认放置于“未知歌单”之下[^3]。 ```python import os import json import requests from bs4 import BeautifulSoup def get_artist_songs(artist_id): url = f"https://music.163.com/api/v1/resource/comments/R_SO_4_{artist_id}?limit=999" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', # Add more header fields as necessary to mimic a real browser request. } response = requests.get(url, headers=headers) if response.status_code != 200: raise Exception(f"Failed to fetch data from {url}") songs_data = response.json() song_list = [] for item in songs_data['hotComments']: try: content = item["content"] liked_count = item["likedCount"] formatted_item = {"comment": content, "likes": liked_count} song_list.append(formatted_item) except KeyError as e: print(f'Missing key: {e}') return song_list if __name__ == "__main__": artist_id = input("请输入想要抓取的歌手ID:") all_songs = get_artist_songs(artist_id) output_dir = './artists/' if not os.path.exists(output_dir): os.mkdir(output_dir) with open(os.path.join(output_dir,f'{artist_id}.json'), mode='w', encoding='utf8') as file_obj: json.dump(all_songs, fp=file_obj, ensure_ascii=False) print('爬取完毕') ``` 此脚本展示了如何基于给定的 Artist ID 抓取相关评论信息并将其导出为 JSON 文件存放在指定位置。实际应用中还需要进一步完善错误处理机制及优化性能表现等方面的工作。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值