https://blog.csdn.net/weixin_36604953/article/details/78592943html
Python新手寫出漂亮的爬蟲代碼2——從json獲取信息
很久沒有寫關於爬蟲的東西了,若是正在讀這篇博客的你看過個人另外一篇《Python新手寫出漂亮的爬蟲代碼1——從html獲取信息》想必已經對一些寫在html中的信息進行過爬取了,今天給你們介紹一下另外一種爬蟲——動態爬蟲。python
1.靜態爬蟲與動態爬蟲
何爲動態爬蟲,html中的信息是靜態的,或者說是經過html語言生成了網頁中的對應信息,是寫好的,你把網頁的html源代碼粘貼過來,你要的信息就在裏面,這種狀況下就是靜態爬蟲,而有的時候咱們會發現咱們須要的信息不在html源碼中,好比電商網站的評論,某些網站的一些條形圖啊,折線圖啊,(這些圖其實是數字,只是經過某種接口傳到網頁上,而後渲染成了圖的形式,其本質上是數字),這些可能頻繁更新的信息(好比評論每小時甚至每分鐘都在更新),這時候,若是將它寫在html中,是一個很難受的過程,由於有一個新評論你就要改寫html,因此對於這種狀況,咱們想要的數據都會存在一個json文件中。正則表達式
這裏須要作一個說明,咱們看網頁源代碼,經過在網頁上鼠標郵件,點選「查看網頁源代碼」出來的纔是html源碼,而經過F12調出的開發者工具中的element或元素中的那些,不是html代碼,而是html代碼的一個超集,它比真實的html代碼內容要多,因此查看信息是否在html中仍是須要點選「查看網頁源代碼」才準確。json
2.json
json是一種數據格式,相似於python中的字典,以key:value的形式存儲信息,是一種目前愈來愈經常使用的方便的數據存儲方式。瀏覽器
3.動態爬蟲思路
動態爬蟲較靜態爬蟲而言難點在於定位數據或信息的存儲位置,而一旦獲取了這個位置(json文件對應的url),那麼就很是簡單了,使用python的json庫能夠對json數據輕鬆的解析,說白了只是根據你要的key提取其value而已,因此動態爬蟲是比較簡單的(固然,這裏還有另外一個問題,是異步加載問題,這個之後有機會再講,異步加載是啥?好比說某個網頁,沒有「下一頁」按鈕,而是用鼠標滾輪或者屏幕右側的滑塊,向下滑就會刷新,你連往下刷多久會到底都不知道,這就是異步加載,異步加載能夠經過抓包工具去解決,也可使用selenium模擬鼠標點擊去解決,之後會講到)。app
4.定位json存儲位置
定位json的位置一般是經過「換頁」來查看Network的變動,在網頁上按F12打開開發者工具,界面放到Network中,而後換頁,查看「js」或是「XHR」中文件的更新,而後一一查看更新的json文件,來定位咱們須要的信息在哪裏。dom
5.實例講解
說了這麼多你可能仍是有點兒糊塗,不要緊,來個例子就懂了,就拿天貓的一個女裝來講吧,其url爲https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-14681080882.119.17398fc89ncLzj&id=529355863153&rn=ec60f51904f6286d9b2d8bb02c8ca5a8&abbucket=5
(這個模特身材還不錯哈哈)異步
請看圖1,咱們點擊紅色方塊中的「累計評價」,就能夠看到以往的評價,按照咱們前一篇爬蟲的講解來講,這個信息可能在html代碼中,好,那麼咱們看一看,按下F12,如圖2所示。 scrapy
圖1
圖2中的1和2位置能夠看到,評論彷彿是在一個標籤中的,可是還記得我前面的說明麼,你在這裏看到的html代碼是真實html代碼的一個超集,比實際的html代碼要多,那麼咱們右鍵鼠標,選擇「查看網頁源代碼」,並把源碼複製粘貼到文本編輯器中,查找圖2中1對應的評論,結果如圖3所示。編輯器
圖2
圖3中居然沒有搜索到這個評論,也就是說圖2的開發者工具欺騙了咱們,too young too sample,sometime naive,哈哈,不要緊,之後每次爬蟲以前都這麼看一看,就知道你要的信息是否是在html中了。好了,既然不在html中,那麼咱們須要去尋找咱們想要的信息在哪裏了。
圖3
按照圖4,在開發者工具中選擇「Network」,來查看網頁其餘組件信息。
圖4
如圖5的紅色方塊,點擊「JS」,不出之外應該是空的,固然若是你那裏不是空的也無所謂,無傷大雅,咱們要的數據就在JS下,只是如今還未顯示出來(還有一些狀況,尤爲是折線圖這些圖像形式的數據,通常會存儲在XHR下,也就是圖5中的粉色圈中,也是.json形式的),接下來咱們就要去尋找存儲評論數據的json文件了。
圖5
此時「JS」下的界面如圖5所示,有多是空的,固然也可能會有一些其餘的東西,接下來看圖6,點擊圖6中A處頁碼「2」,將評論頁切換到第二頁,這時候你會發現B處,也就是JS界面中出現了一個文件(若是你先前圖5中有內容,那此時應該是多出一個文件),這個文件叫「list-detail**********」。咱們的數據就存放在這裏。
有些時候,你換頁後可能會出現或新增多個json文件,不過通常都不會不少,最多也就5個,你只須要挨個點進去看看哪一個存放了你須要的信息便可。
圖6
接下來,咱們雙擊這個文件,或者單擊選中這個文件,複製其url而後粘貼到瀏覽器的地址欄中也可,其內容如圖7所示,這裏紅框標出了其前三條評論。由於咱們是在評論的第二頁打開的這個json,因此它對應的是第二頁的評論內容,而網頁中第二頁評論的前三條如圖8所示。
圖7
能夠看到,數據對上了,咱們已經成功的定位到了評論的位置,圖7的json誠如各位所見,是一個字典的形式,評論內容對應的key爲」rateContent」。
圖8
接下來看一下評論的頁碼是怎麼控制的。如圖9所示,其實兩個url只差了之歌數字,就是圖9紅框標出的」currentPage=」後面的數字,若是是第一頁,數字就是1,若是是第二頁,數字就是2。好了,換頁規律找到了,剩下就是解析json了,就是最簡單的一步。
圖9
關於json的解析我不許備過多解釋了,有python基礎的朋友必定對json這個庫不陌生,我在代碼中以註釋的方式給出吧。本例代碼使用Python3。
6.代碼實戰
import urllib
import urllib.request
import re
from bs4 import BeautifulSoup
import time
import random
import json
import math
# 建立一個文件存儲評論及其餘數據
myfile = open("tm_fz_gn_1_1_1.txt","a")
# 共獲取四個變量,評論者暱稱,是否超級會員,評論時間,評論內容
print("評論者暱稱","是否超級會員","評論時間","comment",sep='|',file=myfile)
stop = random.uniform(0.5,2)
# 獲取頁數
try:
url0 = "https://rate.tmall.com/list_detail_rate.htm?itemId=544442011638&spuId=718591114&sellerId=196993935&order=3¤tPage=1&append=0&content=1&tagId=&posi=&picture=&ua=025UW5TcyMNYQwiAiwQRHhBfEF8QXtHcklnMWc%3D%7CUm5Ockp3S39AeU13QnhDeC4%3D%7CU2xMHDJ7G2AHYg8hAS8XIw0tA18%2BWDRTLVd5L3k%3D%7CVGhXd1llXWBcaFduWmBVb1RvWGVHe0Z9SXRLc05zRnlDfkZ6VAI%3D%7CVWldfS0TMww1CioWIgIsCCNMMWwyVDlrME8iakFhXn5BZEocSg%3D%3D%7CVmhIGCUFOBgkGiMXNwwzBzsbJxkiGTkDOA0tES8ULw81Cj9pPw%3D%3D%7CV2xMHDIcPAA%2FASEcPAM4Az9pPw%3D%3D%7CWGBAED4QMGBaZ1p6RXBKc1NoXWBCfUh0S3NTbVBqSnROblBkMhIvDyEPLxciGSx6LA%3D%3D%7CWWBdYEB9XWJCfkd7W2VdZ0d%2BXmBdfUF0Ig%3D%3D&isg=AnBwr9DL3fao4YAwe7Eb61VPQT4CEVRrBvSVMGrBPUueJRHPEskkk8YHCxu-&needFold=0&_ksTS=1501924984733_1070&callback=jsonp1071"
req0 = urllib.request.Request(url0)
req0.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36')
html0 = urllib.request.urlopen(req0,timeout=500).read()
html0 = bytes.decode(html0,encoding="gbk")
# print(type(html0))
'''
下面這一步是由於這個json不是標準的json,json是一個完徹底全的字典,而這個json是在相似json1234()這個結構的括號中,打開看看這個json你就懂了,因此須要用正則表達式去獲取真實的json(即字典)
'''
js0 = re.search('{"rateDetail(.*)',html0).group()[:-1]
# 將json主要內容存入content
content0 = json.loads(js0)
content = content0['rateDetail']
# print(content.keys())
# print(json.dumps(content0, sort_keys=True, indent=2))
#尾頁
lastpage = int(content['paginator']['lastPage'])
except:
print("獲取尾頁失敗,默認爬取99頁")
lastpage = 99
# 構造循環遍歷每一頁for i in range(1,lastpage): try: url = 'https://rate.tmall.com/list_detail_rate.htm?itemId=544442011638&spuId=718591114&sellerId=196993935&order=3¤tPage='+str(i)+'&append=0&content=1&tagId=&posi=&picture=&ua=025UW5TcyMNYQwiAiwQRHhBfEF8QXtHcklnMWc%3D%7CUm5Ockp3S39AeU13QnhDeC4%3D%7CU2xMHDJ7G2AHYg8hAS8XIw0tA18%2BWDRTLVd5L3k%3D%7CVGhXd1llXWBcaFduWmBVb1RvWGVHe0Z9SXRLc05zRnlDfkZ6VAI%3D%7CVWldfS0TMww1CioWIgIsCCNMMWwyVDlrME8iakFhXn5BZEocSg%3D%3D%7CVmhIGCUFOBgkGiMXNwwzBzsbJxkiGTkDOA0tES8ULw81Cj9pPw%3D%3D%7CV2xMHDIcPAA%2FASEcPAM4Az9pPw%3D%3D%7CWGBAED4QMGBaZ1p6RXBKc1NoXWBCfUh0S3NTbVBqSnROblBkMhIvDyEPLxciGSx6LA%3D%3D%7CWWBdYEB9XWJCfkd7W2VdZ0d%2BXmBdfUF0Ig%3D%3D&isg=AnBwr9DL3fao4YAwe7Eb61VPQT4CEVRrBvSVMGrBPUueJRHPEskkk8YHCxu-&needFold=0&_ksTS=1501924984733_1070&callback=jsonp1071' req = urllib.request.Request(url) req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36') html = urllib.request.urlopen(req,timeout=500).read() html = bytes.decode(html,encoding="gbk") js = re.search('{"rateDetail(.*)', html).group()[:-1] infos0 = json.loads(js) infos = infos0['rateDetail']['rateList'] tiaoshu = 0 for info in infos: try: tiaoshu += 1 time.sleep(stop) ss = "正在爬取第%d頁的第%d條評論,共%d頁" % (i,tiaoshu,lastpage) print(ss) # 用戶姓名 try: user_name = info['displayUserNick'].strip().replace('\n','') except: user_name = "" # 是否黃金會員 try: user_status = info['goldUser'].strip().replace('\n','') except: user_status = "" # 評論時間 try: comment_date = info['rateDate'].strip().replace("\n","") except: comment_date = "" # 評論內容 try: comment = info['rateContent'].strip().replace("\n","").replace('\t','') except: comment = "" print(user_name,user_status,comment_date,comment,sep='|',file=myfile) except: sss = '爬取第%d頁的第%d條評論失敗,跳過爬取' % (i,tiaoshu) print(sss) pass except: print("該產品url獲取失敗,請檢查")myfile.close()12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485到此,爬蟲的第二課——從json獲取信息就結束了,之後會陸續退出selenium、異步加載、scrapy的使用教學和案例。敬請關注哈~--------------------- 做者:夏洛克江戶川 來源:CSDN 原文:https://blog.csdn.net/weixin_36604953/article/details/78592943 版權聲明:本文爲博主原創文章,轉載請附上博文連接!