300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 使用Python抓取网易云音乐所有歌手信息

使用Python抓取网易云音乐所有歌手信息

时间:2019-10-21 08:46:49

相关推荐

使用Python抓取网易云音乐所有歌手信息

思路

1. 构造请求页面的URL

每个页面由歌手分类和歌手名字的大写字母值构成,比如,”/discover/artist/cat?id=1001&initial=65“,就是请求华语男歌手,字母为”A”的所有歌手

2. 请求数据

请求数据使用的是requests包,当请求的网址没有错误并且status_code为200时,返回网页的内容。

注意:这里并没改变请求的headers,也没有使用代理

3. 解析数据

使用lxml包进行html解析,抓取包括歌手id,name,cat,userhome四个信息

4. 存储到MongoDB

存储时将歌手id作为数据表的’_id’,由于歌手id唯一性,可以防止数据库中的文档重复插入

import requestsfrom requests.exceptions import RequestExceptionfrom lxml import etreefrom pymongo import MongoClientfrom concurrent import futuresCATS = {'1001': '华语男歌手','1002': '华语女歌手','1003': '华语组合/乐队','2001': '欧美男歌手','2002': '欧美女歌手','': '欧美乐队/组合','6001': '日本男歌手','6002': '日本女歌手','6003': '日本乐队/组合','7001': '韩国男歌手','7002': '韩国女歌手','7003': '韩国乐队/组合','4001': '其他男歌手','4002': '其他女歌手','4003': '其他乐队/组合'}def get_artists(args):'''根据不同参数请求不同页面,并返回歌手信息:param args: :return: '''url = '/discover/artist/cat?id={}&initial={}'.format(args[0],args[1])result = fetch(url)if result is not None:artists = parse(result,args[0])return artistsdef fetch(url):'''请求连接,成功时(200)返回页面内容:param url: :return: '''try:resp = requests.get(url)except RequestException:return Noneif resp.status_code == 200:return resp.textelse:return Nonedef parse(page,cat_id):'''页面解析,返回当前页面所有的歌手信息:param page: :param cat_id: :return: '''html = etree.HTML(page)ul = html.xpath('//ul[@id="m-artist-box"]')lis = ul[0].xpath('li')artists = []for li in lis:tmp = {}href = li.xpath('a|p/a')tmp['cat'] = CATS[cat_id]tmp['name'] = href[0].text# 使用'_id'存储歌手的id,能够保证插入数据的唯一性tmp['_id'] = href[0].attrib['href'].split('=')[1]# 如果歌手有主页的话,添加主页的信息if len(href) == 2:tmp['userhome'] = href[1].attrib['href']else:tmp['userhome'] = Noneartists.append(tmp)return artistsdef get_args(hot=False):'''根据hot生成请求参数:param hot: :return: '''if hot is False:initials = [i for i in range(65, 91)]initials.append(0)else:initials = [-1]return [[cat_no,initial] for cat_no in CATS.keys() for initial in initials]def get_all_artists(hot=False):'''1. 初始化请求参数2. 初始化存储信息3. 获取并保存:param hot: :return: '''args = get_args(hot)client = MongoClient()db = client['py_netease']if not hot:artists = db['artists']else:artists = db['hot_artists']# 多线程下载,用时约24秒with futures.ThreadPoolExecutor(4) as executor:res = executor.map(get_artists,args)for result in res:try:artists.insert_many(result)except:pass# 单线程下载,用时约1分33秒# for arg in args:#result = get_artists(arg)#try:# artists.insert_many(result)#except:# passif __name__ == '__main__':get_all_artists()

其他

1. 关于多线程

最简单的方法就是使用concurrent.futures包,其他也可以使用threading包。由于抓取属于IO密集型,因此使用多线程会明显改善效率。

2. 关于抓取失败

有可能是IP被禁止访问,返回503错误

3. 最后,发一下效果图,所有歌手一共有3w+条数据,而热门歌手有1500条数据

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。