使用python-aiohttp爬取網易雲音樂
阿新 • • 發佈:2019-01-23
通過上文《使用python-aiohttp搭建微信公眾平臺》,我們已經可以響應來自微信伺服器的請求,接下來,我們為公眾號增加一個線上點歌的功能。
由於本人平時聽歌用的是網易雲音樂,所以就在網上搜了一下,還真找到不少,再考慮到這裡只需要用到網易雲音樂的關鍵詞搜尋,最終鎖定了這篇文章《音樂API推薦–網易音樂API–百度音樂API》,先通過Fiddler抓包看看這篇文章介紹的方法效果咋樣。
GET http://s.music.163.com/search/get/?type=1&s=彩虹&limit=1&offset=0
引數 | 取值 | 說明 |
---|---|---|
type | 1 | 無 |
s | 彩虹 | 關鍵詞 |
offset | 0 | 偏移量 |
limit | 1 | 最大返回結果數 |
其中的offset類似翻頁功能,比如一頁有十首歌曲,就令limit=10,offset=0,返回第一頁,設定limit=10,offset=10來返回第二頁。
返回值如下:
{
"result": {
"songCount": 3919,
"songs": [
{
"id": 413831818,
"name": "彩虹" ,
"artists": [
{
"id": 1207037,
"name": "貓貓村長",
"picUrl": null
}
],
"album": {
"id": 34706315,
"name": "彩虹" ,
"artist": {
"id": 0,
"name": "",
"picUrl": null
},
"picUrl": "http://p1.music.126.net/e2P6AA498KaJpQ_BGrfWGw==/17993507788684015.jpg"
},
"audio": "http://m2.music.126.net/pDFup5BuOFC28iCopRj2QQ==/3251255884973388.mp3",
"djProgramId": 0,
"page": "http://music.163.com/m/song/413831818"
}
]
},
"code": 200
}
在返回的json資料中,songCount表示以彩虹為關鍵詞搜尋到的歌曲總數,songs是返回的歌曲列表,其中,name表示歌曲名;artists與album分別包含歌手與唱片資訊;audio與page分別為歌曲與歌曲頁面的連結。既然返回結果沒問題,接下來我們就用aiohttp搭建客戶端來發送GET請求,並從返回值中提取歌曲名、歌手名、唱片圖片與歌曲頁面等資訊。
新建檔案netease_music3.py,程式碼如下:
import asyncio
from aiohttp import ClientSession
__MUSIC_NUM = 1 # hu 返回的最大歌曲數
async def __fetch(url,data,loop):
try:
async with ClientSession(loop=loop) as session:
# hu 傳送GET請求,params為GET請求引數,字典型別
async with session.get(url, params=data,timeout=5) as response:
# hu 以json格式讀取響應的body並返回字典型別
return await response.json()
except Exception as ex:
print('__fetch:%s' % ex)
async def getMusicInfo(keyword,offset, loop):
global __MUSIC_NUM
urlFace = 'http://s.music.163.com/search/get'
dataMusic = {'type': '1',
's': keyword,
'limit': str(__MUSIC_NUM),
'offset': str(offset)}
result = None
try:
task = asyncio.ensure_future(__fetch(urlFace, dataMusic,loop),loop=loop)
taskDone = await asyncio.wait_for(task,timeout=5)
if 'result' not in taskDone:
return result
for song in taskDone['result']['songs']:
if result is None:
result = [{'name':song['name'],
'artist':song['artists'][0]['name'],
'picUrl':song['album']['picUrl'],
'audio':song['audio'],
'page':song['page']}]
else:
result.append({'name': song['name'],
'artist': song['artists'][0]['name'],
'picUrl': song['album']['picUrl'],
'audio': song['audio'],
'page': song['page']})
except Exception as ex:
print('getMusicInfo:%s' % ex)
return result
def __main():
loop = asyncio.get_event_loop()
music = '彩虹'
player = '喬楚熙'
task = asyncio.ensure_future(getMusicInfo(music+player,1,loop),loop=loop)
taskDone = loop.run_until_complete(task)
for key,value in taskDone[0].items():
print(key+':'+value)
loop.close()
if __name__ == '__main__':
__main()
返回值:
name:彩虹
artist:喬楚熙
picUrl:http://p1.music.126.net/dAzMzFp6ucMVcSSPn0cFqg==/19049038951250054.jpg
audio:http://m2.music.126.net/5f0_bUm6eMrx4o_ZN4OFQg==/2074778441644241.mp3
page:http://music.163.com/m/song/4873072
關於asyncio模組的基本概念可參考《使用python-aiohttp搭建微信公眾平臺》,這裡就不一一註釋了。接下來,我們在微信公眾平臺上新增線上點歌功能。
import netease_music3
在if語句中新增程式碼如下:
if MsgType.lower() == 'text': # hu 文字訊息
reg = r'''<Content><!\[CDATA\[(.*?)\]\]></Content>
<MsgId>(.*?)</MsgId>'''
Content, MsgId = re.findall(reg, info)[0]
resp = await netease_music3.getMusicInfo(Content, 0, request.app.loop)
if resp is None:
Content = '要不換首歌吧,這個真找不到啊'
result = '''<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>''' % (FromUserName, ToUserName, CreateTime, MsgType, Content)
else:
MsgType = 'news'
MusicCount = len(resp)
musics = [None] * MusicCount
for ii, music in zip(range(MusicCount), resp):
musics[ii] = '''
<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
''' % ('%s-%s' % (music['name'], music['artist']), music['artist'], music['picUrl'], music['page'])
result = '''<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<ArticleCount>%d</ArticleCount>
<Articles>
%s
</Articles>
</xml>''' % (FromUserName, ToUserName, CreateTime, MsgType, MusicCount, ''.join(musics))
執行以上程式碼就可以在公眾號裡輸入關鍵詞點歌啦~