Ajax數據爬取
什麼是Ajax,官方的來說,它不是一們編程語言,而是利用JavaScript在保證頁面不被刷新、頁面鏈接不改變的情況下與服務器交換數據並更新部分網頁的技術。
通俗的來說,這個技術其實應用非常廣泛,比如說,你在用網頁瀏覽的時候,下拉最右邊的進度條(可能我用的詞不規範哈)然後先出現提示內容正在加載,不到一秒鐘的時間就出現了新的微博內容,但你所訪問的url鏈接並沒有改變,但頁面的內容卻更新了,這就是Ajax技術。
Ajax有一個特殊的請求類型,叫做 xhr。在進行Ajax分析時打開Chrome的Network,有一個圖標XHR,這裏就是幫你過濾後的所有Ajax請求。(以手機端微博網頁爲例,如圖)
這裏就是所有的Ajax請求,你可以接着下拉,就會發現這裏的響應內容就會增多。
大家是不是對Ajax請求有了初步的瞭解了呢,接下來就進入主題,爬取指定人的微博內容。
首先打開手機端微博的登陸網址,登上自己的微博:
url = 'https://m.weibo.cn'
以我的微博爲例:
之後就是打開你的特別關注,然後搜索你喜歡的那個人,進入她的微博主頁,然後F12,到Network界面下,選擇XHR,F5刷新以下就會出現Ajax響應:
然後接着下拉,找尋加載頁面返回內容的Ajax請求響應,並打開對其進行分析(很容易找到的):
很容易找到在所選響應下的data->cards->mblog中找到自己想要的內容,並發現其時以json形式返回的,那麼我就開始分析其請求頭和所攜帶的參數列表,尋找其中的不同,以構造自己的Ajax請求頭:
觀察發現在參數列表當中,剛點進去微博主頁刷新得到的參數列表中沒有since_id這一項,而下拉內容再返回的響應參數列表中卻出現的不同的since_id,可以發現再請求響應過程中只有since_id在改變,其它參數都沒有變(since_id是用來控制頁面的增加的)
在搞清楚這些後我們就可以構造自己的頭部,模擬Ajax請求從而爬取內容,上代碼!
用到的包:
from urllib.parse import urlencode
from pyquery import PyQuery as py
import requests
構造頭部和參數列表,來獲得返回內容:
def get_information(since_id = '',uid = 0,):
#X-Requested-With 用來標識Ajax請求,必須得有
#Referer 用來指明請求來源 必須有
#User-Agent 僞裝瀏覽器,必須有
headers = {'Referer': 'https://m.weibo.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'}
params = {
'uid': uid,
'luicode': 10000011,
'lfid': '231093_-_selffollowed',
'type': int(uid),
'value': 5768045317,
'containerid': '107603' + str(uid),
'since_id': since_id
}
# urlencode() 方法將參數轉化爲URL的GET請求參數
url = 'https://m.weibo.cn/api/container/getIndex?' + urlencode(params)
response = requests.get(url,headers = headers)
#獲得返回的 json 內容,做分析
json_text = response.json()
#獲得 since_id 爲增加頁面做準備
since_id = json_text.get('data').get('cardlistInfo').get('since_id')
return json_text,since_id
分析JSON內容:
def parse_json(json):
items = json.get('data').get('cards')
for item in items:
item = item.get('mblog')
weibo = {}
weibo['發表時間'] = item.get('created_at')
weibo['手機類型'] = item.get('source')
weibo['內容'] = py(item.get('text')).text()
weibo['圖片鏈接'] = item.get('bmiddle_pic')
weibo['點贊數'] = item.get('attitudes_count')
weibo['評論數'] = item.get('comments_count')
yield weibo
主函數:
if __name__ == '__main__':
#uid 你所要爬取的微博的ID,在響應的參數列表中可以得到,圖中可以找到
uid = 5768045317
#p 爬取的頁數
p = 3
#獲得返回的 JSON 內容 和 since_id
s = get_information(since_id = '',uid = uid)
#解析 JSON
parse_json(s[0])
#輸出解析後的內容
for i in parse_json(s[0]):
print(i)
'''
#多頁爬取
for i in range(p):
s = get_information(since_id = s[1],uid = uid)
for i in parse_json(s[0]):
print(i)
'''
最後的後臺結果:
我爬取的是我女朋友的微博,所以後面的就不展示啦,大家可以自己試一試
此代碼獻給我下鋪的兄弟,希望他再也不用熬夜刷微博😄當然這個代碼還可以將所有的照片都爬取下來,這之後會實現的!