Python爬虫笔记——解析json数据(以周杰伦歌单为例)及Headers
一、Network
Network能夠記錄瀏覽器的所有請求。我們最常用的是:ALL(查看全部)/XHR(僅查看XHR)/Doc(Document,第0個請求一般在這里),有時候也會看看:Img(僅查看圖片)/Media(僅查看媒體文件)/Other(其他)。最后,JS和CSS,則是前端代碼,負責發起請求和頁面實現;Font是文字的字體;而理解WS和Manifest,需要網絡編程的知識,倘若不是專門做這個,則不需要了解。
我們平時使用瀏覽器上網的時候,經常有這樣的情況:瀏覽器上方,它所訪問的網址沒變,但是網頁里卻新加了內容。
典型代表:如購物網站,下滑自動加載出更多商品。在線翻譯網站,輸入中文實時變英文。再比如,我們正在爬取的QQ音樂案例,如果你對“周杰倫”的搜索結果進行翻頁,瀏覽器上方顯示的網址,也不會發生變化。
在Network,有非常重要的一類請求是XHR(或Fetch),因為有它的存在,人們不必刷新/跳轉網頁,即可加載新的內容。隨著技術發展,XHR的應用頻率越來越高,我們常常需要在這里找我們想要的數據。
Headers:標頭(請求信息)、Preview:預覽、Response:原始信息、Timing:時間。
XHR的功能是傳輸數據,其中有非常重要的一種數據是用json格式寫成的,和html一樣,這種數據能夠有組織地存儲大量內容。json的數據類型是“文本”,在Python語言當中,我們把它稱為字符串。我們能夠非常輕易地將json格式的數據轉化為列表/字典,也能將列表/字典轉為json格式的數據。
如何解析json數據?答案如下:
而如果你想在Python語言中,實現列表/字典轉json,json轉列表/字典,則需要借助json模塊。
也可閱讀它的官方文檔來了解,地址在這里:https://docs.python.org/3/library/json.html
一個簡單的應用示例,是這樣:
import json # 引入json模塊 a = [1,2,3,4] # 創建一個列表a。 b = json.dumps(a) # 使用dumps()函數,將列表a轉換為json格式的字符串,賦值給b。 print(b) # 打印b。 print(type(b)) # 打印b的數據類型。 c = json.loads(b) # 使用loads()函數,將json格式的字符串b轉為列表,賦值給c。 print(c) # 打印c。 print(type(c)) # 打印c的數據類型。打印結果:
[1, 2, 3, 4] <class 'str'> [1, 2, 3, 4] <class 'list'>二、爬取QQ音樂周杰倫的前20個歌曲名、所屬專輯、播放時長,以及播放鏈接的實例
import requests # 引用requests庫 res_music = requests.get('https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=60997426243444153&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=%E5%91%A8%E6%9D%B0%E4%BC%A6&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0') # 調用get方法,下載這個字典 json_music = res_music.json() # 使用json()方法,將response對象,轉為列表/字典 list_music = json_music['data']['song']['list'] # 一層一層地取字典,獲取歌單列表 for music in list_music: # list_music是一個列表,music是它里面的元素print(music['name'])# 以name為鍵,查找歌曲名print('所屬專輯:'+music['album']['name'])# 查找專輯名print('播放時長:'+str(music['interval'])+'秒')# 查找播放時長print('播放鏈接:https://y.qq.com/n/yqq/song/'+music['mid']+'.html\n')# 查找播放鏈接打印結果:
Mojito 所屬專輯:Mojito 播放時長:185秒 播放鏈接:https://y.qq.com/n/yqq/song/001glaI72k8BQX.html晴天 所屬專輯:葉惠美 播放時長:269秒 播放鏈接:https://y.qq.com/n/yqq/song/0039MnYb0qxYhV.html一路向北 所屬專輯:J III MP3 Player 播放時長:295秒 播放鏈接:https://y.qq.com/n/yqq/song/001xd0HI0X9GNq.html七里香 所屬專輯:七里香 播放時長:299秒 播放鏈接:https://y.qq.com/n/yqq/song/004Z8Ihr0JIu5s.html稻香 所屬專輯:魔杰座 播放時長:223秒 播放鏈接:https://y.qq.com/n/yqq/song/003aAYrm3GE0Ac.html告白氣球 所屬專輯:周杰倫的床邊故事 播放時長:215秒 播放鏈接:https://y.qq.com/n/yqq/song/003OUlho2HcRHC.html聽媽媽的話 所屬專輯:依然范特西 播放時長:265秒 播放鏈接:https://y.qq.com/n/yqq/song/002hXDfk0LX9KO.html等你下課 所屬專輯:等你下課 播放時長:270秒 播放鏈接:https://y.qq.com/n/yqq/song/001J5QJL1pRQYB.html夜曲 所屬專輯:十一月的蕭邦 播放時長:226秒 播放鏈接:https://y.qq.com/n/yqq/song/001zMQr71F1Qo8.html半島鐵盒 所屬專輯:八度空間 播放時長:319秒 播放鏈接:https://y.qq.com/n/yqq/song/002OKIox28ad9a.html不能說的秘密 所屬專輯:不能說的秘密 電影原聲帶 播放時長:296秒 播放鏈接:https://y.qq.com/n/yqq/song/002MXZNu1GToOk.html擱淺 所屬專輯:七里香 播放時長:240秒 播放鏈接:https://y.qq.com/n/yqq/song/001Bbywq2gicae.html青花瓷 所屬專輯:我很忙 播放時長:239秒 播放鏈接:https://y.qq.com/n/yqq/song/002qU5aY3Qu24y.html以父之名 所屬專輯:葉惠美 播放時長:342秒 播放鏈接:https://y.qq.com/n/yqq/song/001n4C3p1yv0FU.html給我一首歌的時間 所屬專輯:魔杰座 播放時長:253秒 播放鏈接:https://y.qq.com/n/yqq/song/004BhQke4adHcf.html愛的飛行日記 所屬專輯:跨時代 播放時長:255秒 播放鏈接:https://y.qq.com/n/yqq/song/003CxS6w14OQyM.html簡單愛 所屬專輯:范特西 播放時長:270秒 播放鏈接:https://y.qq.com/n/yqq/song/0009BCJK1nRaad.html蒲公英的約定 所屬專輯:我很忙 播放時長:247秒 播放鏈接:https://y.qq.com/n/yqq/song/004Yi5BD3ksoAN.html煙花易冷 所屬專輯:跨時代 播放時長:263秒 播放鏈接:https://y.qq.com/n/yqq/song/004emQMs09Z1lz.html楓 所屬專輯:十一月的蕭邦 播放時長:275秒 播放鏈接:https://y.qq.com/n/yqq/song/003KtYhg4frNXC.html以上代碼只能爬取20個代碼使它能爬取很多很多歌曲,而不只是爬取20個。所以要學會怎么翻頁。
使用瀏覽器打開QQ音樂官網,搜索周杰倫。然后打開檢查面板里的Network,刷新這個頁面。找到隱藏有歌曲列表的那個XHR,它的名字應該叫client_search……之類,點開它,選中Headers,你能看到Request Url,很長的一個地址。現在,保持General打開,保持Response Headers和Request Headers關閉。我們點開Query String Parametres。它里面的內容,正是請求所附帶的參數,Query String Parametres,它的中文翻譯是:查詢字符串參數。這個面板用類似字典的形式,呈現了各個參數的鍵值,閱讀體驗會好一些。
三、如何帶參數請求數據
讀懂參數,有兩個重要的方法是“觀察”和“比較”。“觀察”指的是閱讀參數的鍵與值,嘗試理解它的含義。“比較”指的是比較兩個相近的XHR——它們有哪些不同,對應的頁面顯示內容有什么不同。
現在,我們來觀察比較,不同頁碼的歌曲列表,它們url的不同。依然在搜索“周杰倫”的結果頁,點擊第2頁、第3頁進行翻頁,此時Network會多加載出2個XHR,它們的Name都是client_search…。
分別點開它們的Query String Parametres,比較參數之間有什么不同。點擊Enter(回車)鍵,告訴你答案。
在此,只有一個參數變化。這個參數是p。第1頁p的值為1,第二、第三頁的值則為2和3。說明p代表的應該就是頁碼。
如果你再去對比它們的url,也能發現同樣的事實:url整個兒都是
我們去寫一個循環,每次循環去更改p的值,這樣不就能實現爬取好多好多歌曲了嗎?
代碼如下:
四、params
事實上,requests模塊里的requests.get()提供了一個參數叫params,可以讓我們用字典的形式,把參數傳進去。
所以,其實我們可以把Query String Parametres里的內容,直接復制下來,封裝為一個字典,傳遞給params。只是有一點要特別注意:要給他們打引號,讓它們變字符串。
代碼如下:
打開Network,選中All,點擊刷新。第0個請求一般都會是html。我們點開第0個請求來看看(看Preview或Response都可以),里面有沒有我們想要的評論信息。如果沒有找到就去看XHR,常規來說我們有兩種方法來尋找XHR:閱讀它們的name看看哪個可能是評論;或者是一個一個翻。
介紹一個簡單的小技巧:先把Network面板清空,再點擊一下評論翻頁,看看有沒有多出來的新XHR,多出來的那一個,就應該是和評論相關的啦。
總結技巧:
我們點開這個請求的Preview,能夠在[‘comment’][‘commentlist’]里找到評論列表。列表的每一個元素都是字典,字典里鍵rootcommentcontent對應的值,就是我們要找的評論。
剩下的事情就簡單了。我們去模擬這個請求,解析json,提取想要的內容就好。
點擊Headers,在General里看鏈接,在Query String Parametres里看參數,多翻幾頁評論列表,總結參數的規律。
XHR有兩個參數在不斷變化:一個是pagenum,一個lasthotcommentid。其中pagenum好理解,就是頁碼,但是lastcommentid是什么?
我們來閱讀這個英文lasthotcommentid,它的含義是:上一條熱評的評論id。基于此,我們可以做一個猜想:每一頁的請求,參數lasthotcommentid的值,是上一頁的最后一條評論,所對應的id。
這樣寫好像也可以,可以忽略掉lasthotcommentid
import requests # 引用requests模塊 url = 'https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg' #commentid = '' # 設置一個初始commentid for x in range(2):params = {'g_tk':'5381','loginUin':'0','hostUin':'0','format':'json','inCharset':'utf8','outCharset':'GB2312','notice':'0','platform':'yqq.json','needNewCode':'0','cid':'205360772','reqtype':'2','biztype':'1','topid':'102065756','cmd':'8','needcommentcrit':'0','pagenum':str(x),'pagesize':'25','lasthotcommentid':'','domain':'qq.com','ct':'24','cv':'101010 '}# 將參數封裝為字典,其中pagenum和lastcommentid是特殊的變量res_comment = requests.get(url,params=params)# 調用get方法,下載評論列表json_comment = res_comment.json()# 使用json()方法,將response對象,轉為列表/字典list_comment = json_comment['comment']['commentlist']# 一層一層地取字典,獲取評論列表for comment in list_comment:# list_comment是一個列表,comment是它里面的元素print(comment['rootcommentcontent']+'\n')# 輸出評論#commentid = list_comment[24]['commentid']# 將最后一個評論的id賦值給comment,準備開始下一次循環五、Request Headers
如果有一天,你真的需要爬取這一萬多條評論,將for循環執行成百上千次。
那么,你最好將自己的爬蟲偽裝成真實的瀏覽器——因為在這種情況下,服務器很可能拒絕爬蟲訪問。甚至有的網站,一開始就不允許爬蟲訪問。如,知乎、貓眼電影。
服務器通過什么識別我們是真實瀏覽器,還是Python爬蟲的呢?
每一個請求,都會有一個Requests Headers,我們把它稱作請求頭。它里面會有一些關于該請求的基本信息,比如:這個請求是從什么設備什么瀏覽器上發出?這個請求是從哪個頁面跳轉而來?
如上圖,user-agent會記錄你電腦的信息和瀏覽器版本(如我的,就是windows10的64為操作系統,使用谷歌瀏覽器)。origin和referer則記錄了這個請求,最初的起源是來自哪個頁面。它們的區別是referer會比origin攜帶的信息更多些。
如果我們想告知服務器,我們不是爬蟲是一個正常的瀏覽器,就要去修改user-agent。倘若不修改,那么這里的默認值就會是Python,會被瀏覽器認出來。
而對于爬取某些特定信息,也要求你注明請求的來源,即origin或referer的內容。比如我有試過,在爬取歌曲詳情頁里的歌詞時,就需要注明這個信息,否則會拿不到歌詞。你可以在寫練習的時候進行嘗試。
如何添加Requests Headers?
Requests模塊允許我們去修改Headers的值。點擊它的官方文檔,搜索“user-agent”,你會看到:
如上,只需要封裝一個字典就好了。和寫params非常相像。
而修改origin或referer也和此類似,一并作為字典寫入headers就好。就像這樣:
爬取前五頁歌詞:
import requestsfor i in range(1,6):res=requests.get('https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&remoteplace=txt.yqq.lyric&searchid=91763561204056573&aggr=0&catZhida=1&lossless=0&sem=1&t=7&p={}&n=5&w=%E5%91%A8%E6%9D%B0%E4%BC%A6&g_tk=1676601595&loginUin=835926124&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0'.format(i))lyric=res.json()contents=lyric['data']['lyric']['list']for content in contents:print(content['content'].replace('\\n','\n'))#\\n表示真的\n字符而不是換行符,將歌詞中的\n替換成換行符。print('---------------------------------')總結
以上是生活随笔為你收集整理的Python爬虫笔记——解析json数据(以周杰伦歌单为例)及Headers的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言 rpg游戏,浅谈RPG游戏设计(
- 下一篇: 毕业三年,我从鉴黄师转行到阿里做前端