https://blog.csdn.net/weixin_36604953/article/details/78592943
Python新手寫出漂亮的爬蟲代碼2——從json獲取信息
好久沒有寫關於爬蟲的東西了,如果正在讀這篇博客的你看過我的另一篇《Python新手寫出漂亮的爬蟲代碼1——從html獲取信息》想必已經對一些寫在html中的信息進行過爬取了,今天給大家介紹一下另一種爬蟲——動態爬蟲。
1.靜態爬蟲與動態爬蟲
何為動態爬蟲,html中的信息是靜態的,或者說是通過html語言生成了網頁中的對應信息,是寫好的,你把網頁的html源代碼粘貼過來,你要的信息就在里面,這種情況下就是靜態爬蟲,而有的時候我們會發現我們需要的信息不在html源碼中,比如電商網站的評論,某些網站的一些條形圖啊,折線圖啊,(這些圖實際上是數字,只是通過某種接口傳到網頁上,然后渲染成了圖的形式,其本質上是數字),這些可能頻繁更新的信息(比如評論每小時甚至每分鍾都在更新),這時候,如果將它寫在html中,是一個很難受的過程,因為有一個新評論你就要改寫html,所以對於這種情況,我們想要的數據都會存在一個json文件中。
這里需要做一個說明,我們看網頁源代碼,通過在網頁上鼠標郵件,點選“查看網頁源代碼”出來的才是html源碼,而通過F12調出的開發者工具中的element或元素中的那些,不是html代碼,而是html代碼的一個超集,它比真實的html代碼內容要多,所以查看信息是否在html中還是需要點選“查看網頁源代碼”才准確。
2.json
json是一種數據格式,類似於python中的字典,以key:value的形式存儲信息,是一種目前越來越常用的方便的數據存儲方式。
3.動態爬蟲思路
動態爬蟲較靜態爬蟲而言難點在於定位數據或信息的存儲位置,而一旦獲取了這個位置(json文件對應的url),那么就非常簡單了,使用python的json庫可以對json數據輕松的解析,說白了只是根據你要的key提取其value而已,所以動態爬蟲是比較簡單的(當然,這里還有另一個問題,是異步加載問題,這個以后有機會再講,異步加載是啥?比如說某個網頁,沒有“下一頁”按鈕,而是用鼠標滾輪或者屏幕右側的滑塊,向下滑就會刷新,你連往下刷多久會到底都不知道,這就是異步加載,異步加載可以通過抓包工具去解決,也可以使用selenium模擬鼠標點擊去解決,以后會講到)。
4.定位json存儲位置
定位json的位置通常是通過“換頁”來查看Network的變更,在網頁上按F12打開開發者工具,界面放到Network中,然后換頁,查看“js”或是“XHR”中文件的更新,然后一一查看更新的json文件,來定位我們需要的信息在哪里。
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所示。
圖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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
到此,爬蟲的第二課——從json獲取信息就結束了,以后會陸續退出selenium、異步加載、scrapy的使用教學和案例。敬請關注哈~
---------------------
作者:夏洛克江戶川
來源:CSDN
原文:https://blog.csdn.net/weixin_36604953/article/details/78592943
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!