Ajax動態網頁載入爬取新浪微博某關鍵詞下的資訊

2020-10-12 13:00:18

Ajax動態網頁載入爬取新浪微博某關鍵詞下的資訊

前言

有些時候我們使用瀏覽器檢視頁面正常顯示的資料與使用requests抓取頁面html得到的資料不一致,這是因為requests獲取的是原始的HTML檔案,而瀏覽器中的頁面是經過JavaScript處理資料後的結果。這些處理過的資料可能是通過Ajax載入的,可能包含HTML檔案中,可能經過特定演演算法計算後生成的。

一、Ajax原理

1、什麼是Ajax?
Ajax全稱為Asynchronous JavaScript and XML,即為非同步的JavaScript(JS語言)和XML(萬能的資料傳輸格式)。
2、非同步化?
Ajax的工作原理相當於在使用者和伺服器之間加了—箇中間層(AJAX引擎),使使用者操作與伺服器響應非同步化。並不是所有的使用者請求都提交給伺服器。像—些資料驗證和資料處理等都交給Ajax引擎自己來做,只有確定需要從伺服器讀取新資料時再由Ajax引擎代為向伺服器提交請求它能夠利用,JavaScript在保證不被重新整理,連線不變的情況下,伺服器交換資料並更新部分網頁的技術。像傳統的網頁(不使用Ajax)若要更新網頁內容,必須重新載入網頁,比如貓眼、豆瓣等。下圖為對比圖:
在這裡插入圖片描述

在這裡插入圖片描述

3、範例
瀏覽網頁的時候,我們發現很多網頁都有下滑檢視更多的選項。比如,就拿新浪微博主頁來說。一直往下滑,看到幾個微博之後就沒有了,而是會出現一個載入的動畫,很快就出現了新的微博內容,這個過程就是Ajax載入的過程

二、準備環境+爬取網站

ananconda3——spyder
谷歌瀏覽器
https://m.weibo.cn/

三、網頁分析與定位

1、本次爬取選取「奪冠」這一關鍵詞

在這裡插入圖片描述2、檢查元素——Network——XHR——Ctrl+R

在這裡插入圖片描述3、滑動頁面,依次檢視前三頁page,Request URL中包含多個引數
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述選了前三頁觀察,發現在Request URL裡面除了最後page=2,page=3,其他引數都不發生變化
4、觀察Preview裡面的資訊
想要獲取的資訊都在data——cards——mblog下面

在這裡插入圖片描述在這裡插入圖片描述
分別查詢三個頁面發現,只有在第一頁中時,有些cards下面不存在mblog,也就是說爬出來的內容可能會為空,所以本次爬取我捨去第一頁內容不全的,從page=2開始,這樣可以保證爬出來的內容比較全。

三、程式碼實現

1、匯入庫

from urllib.parse import urlencode
import requests
import json

使用urlencode主要用於正常識別輸入的漢字、空格以及其他特殊字元,由於url中傳入了部分引數,所以需識別引數拼接為完整的url
輸出格式為物件格式:{「key1」:obj,「key2」:obj,「key3」:obj…},所以匯入json包
2、解析頁面
定義一個獲取頁面的函數,其中的引數params包含如下所示

在這裡插入圖片描述
除了page以外,其他引數均不變。定義一個base_url,所有網頁的base_url為同一個。

base_url='https://m.weibo.cn/api/container/getIndex?'

在這裡插入圖片描述這裡需要用到urlencode對引數進行轉化拼接,使其轉化並生成出每一頁完整的url

def get_page(page):
    params = {
        'containerid':'231522type=1&t=10&q=#奪冠#',
        'page_type':'searchall',
        'isnewpage':'1',
        'luicode':'10000011',
        'lfid':'100103type=38&q=奪冠&t=0',
        'page_type': 'searchall',
        'page':page
    }
    url = base_url + urlencode(params)
    try:
        rq = requests.get(url,headers = headers)
        if rq.status_code == 200 :
            return rq.json()
    except rq.ConnectionError as e:
        print('程式錯誤',e.args)

3、定位id和raw_text
第一個函數返回rq.json(),目的是獲取如下介面的全部解析碼
在這裡插入圖片描述print(re.json())後,輸出全部內容
在這裡插入圖片描述
j = get_page(page)返回那個解析頁面,從解析頁面裡面找data——cards,items為cards下面所有的東西,我只想獲得mblog下的id和raw_text,所以用了一個迴圈。先找到mblog用item接收,再再item下找到id用id接收,再找raw_text用raw_text接收,用append進行列表的依次新增,得到 all_id和all_raw_text。最後轉化為字典形式

def parse_page(j):
        items = j['data']['cards']
        all_id=[]
        all_raw_text=[]
        for item in items:
            item = item['mblog']
            id=item['id']
            raw_text=item['raw_text']
            all_id.append(id)
            all_raw_text.append(raw_text)
        weibo = dict(zip(all_id,all_raw_text))      #zip,將兩個列表合併成一個字典
        return weibo

4、存入txt檔案
存入為json格式

def write_text(result):
    with open('關鍵詞資訊.txt','a',encoding='utf-8') as f:
            f.write(json.dumps(result, ensure_ascii=False) + '\n')
            f.write('\n')
    f.close()

5、主函數呼叫
Referer,User-Agent,X-Reuestes-With均在網頁裡

在這裡插入圖片描述

if __name__ == '__main__':
    base_url = 'https://m.weibo.cn/api/container/getIndex?'
    headers = {"Referer": 'https://m.weibo.cn/search?containerid=100103type%3D1%26q%3D%E5%A4%BA%E5%86%A0',
               "User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
               "X-Requested-With":'XMLHttpRequest'}
    for page in range(2,50):
        j = get_page(page)
        result = parse_page(j)
        print(result)
        write_text(result)

四、結果展示

每個id對應一條微博資訊
在這裡插入圖片描述