【python實現網絡爬蟲(16)】JSON網易動態新聞爬取(ajax請求爬取信息過程詳解,附全部源代碼)

1. Ajax 介紹

Ajax 即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML),是指一種創建交互式、快速動態網頁應用的網頁開發技術,無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。
通過在後臺與服務器進行少量數據交換,Ajax 可以使網頁實現異步更新。這意味着可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。(百度百科),網易新聞的頁面就屬於這一類,如下,只要一直往下拉,新聞就會一直出現
在這裏插入圖片描述

2. 爬取邏輯

【找到新聞資訊所在位置】 -> 【確定資源的url】 -> 【獲取json數據】 -> 【按需求獲取數據並存入數據庫或者保存本地】

針對爬取邏輯封裝兩個函數:

1) 獲取資源url的函數

    def get_url(n):

        n:爬取數據的頁數
        return返回值: json數據對應url的列表

2) 獲取需求數據並存入數據庫

     def get_data(url,dic_h,table):

        url:json數據對應的url
        dic_h:請求頭
        table:數據庫表格
        return返回值:數據爬取量計數

3. 資源url獲取

1) 解析json數據文件

首先解析一下網易新聞的頁面,在某一新聞頁面(比如這裏選擇的就是’要聞’界面),右鍵檢查,進行測試,和之前獲取headers和cookies的操作步驟類似,尋找json數據接口

操作如下:【右鍵進入檢查界面】-> 【選中菜單欄Network】-> 【點擊刷新按鈕】-> 【查找右下角中的文件】-> 【找到包含json數據的文件】-> 【下拉左側原界面】-> 【按規律找到全部包含json數據的文件】

圖解如下:(因爲找到包含json數據的文件是cm_開頭的,所以爲了過濾掉其他的信息文件,這裏直接就只查看所有包含json數據的文件,可以看出沒刷新一次頁面就會有一個callback文件出現在Name欄下面)
在這裏插入圖片描述
2) 確定json文件對應的url

在上面的步驟的基礎上,點擊Preview左側的Headers,其中Request URL後面的內容就是json數據對應的url了,對應如下

u1 = https://temp.163.com/special/00804KVA/cm_yaowen20200213.js?callback=data_callback
u2 = https://temp.163.com/special/00804KVA/cm_yaowen20200213_02.js?callback=data_callback
u3 = https://temp.163.com/special/00804KVA/cm_yaowen20200213_03.js?callback=data_callback
u4 = https://temp.163.com/special/00804KVA/cm_yaowen20200213_04.js?callback=data_callback
u5 = https://temp.163.com/special/00804KVA/cm_yaowen20200213_05.js?callback=data_callback

這裏列舉了前五頁的url,是不是就像最初爬取網頁那樣也類似的規律呢,也就是第一頁的url是可以寫成xxx20200213_01.js?xxx類似的格式呢?可以嘗試一下,在瀏覽器界面輸入下面這個網址,看看是否真的有規律可循,如下

https://temp.163.com/special/00804KVA/cm_yaowen20200213_01.js?callback=data_callback

–> 輸出結果爲:(按照相同的方式,發現其他的網頁都可以按照原網址進行打開,也就是說這裏的首頁的url是不符合之前爬蟲的網頁的規律的,因此需要單獨進行判斷)
在這裏插入圖片描述
3) 封裝第一個函數,返回url列表

def get_url(n):
    urllst = []
    url_fixed = 'https://temp.163.com/special/00804KVA/cm_yaowen20200213.js?callback=data_callback'
    urllst.append(url_fixed)
    urllst.extend([f'https://temp.163.com/special/00804KVA/cm_yaowen20200213_0{i}.js?callback=data_callback' for i in range(2,n+1)])
    # for i in range(2,n+1):
    #     urllst.append(f'https://temp.163.com/special/00804KVA/cm_yaowen20200213_0{i}.js?callback=data_callback')
    return urllst

get_url(5)

–> 輸出結果爲:(對比可以發現這五條數據和在網頁上找的url是一致的,在瀏覽器界面打開後均有數據返回)

['https://temp.163.com/special/00804KVA/cm_yaowen20200213.js?callback=data_callback',
 'https://temp.163.com/special/00804KVA/cm_yaowen20200213_02.js?callback=data_callback',
 'https://temp.163.com/special/00804KVA/cm_yaowen20200213_03.js?callback=data_callback',
 'https://temp.163.com/special/00804KVA/cm_yaowen20200213_04.js?callback=data_callback',
 'https://temp.163.com/special/00804KVA/cm_yaowen20200213_05.js?callback=data_callback']
5. 需求數據的爬取並將數據存入數據庫

1) 先配置數據庫參數

這裏使用mongo數據庫作爲數據存儲,比較簡單便捷,總共只需要四行代碼就配置好數據庫,關於mongo數據庫的安裝可以查看mongo快速入門

#導入數據庫模塊
import pymongo  
# 鏈接上服務器
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
#創建一個數據庫
db = myclient['騰訊新聞']
#在該數據庫下創建一個'表格'保存數據
table = db['data1']

2) 數據爬取試錯

在進行大量數據爬取之前,先測試一下能否進行某一頁的信息數據的獲取,如果沒有問題了再進行下一步操作,這樣就可以避免出現問題後再回過頭來查找錯誤,節省時間。

在將數據清洗爲json可轉化的數據類型過程中,要查找位置索引的問題,在之前的python爬取酷狗音樂中已經介紹過,下面直接給出代碼

def get_data(url,dic_h,table):
    count = 0
    ri = requests.get(url,headers = dic_h)
    start = ri.text.index('[')
    end = ri.text.index('])') + 1
    datas = json.loads(ri.text[start:end])
    return datas

urllst = get_url(5)
dic_h = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
get_data(urllst[0],dic_h,table)

–> 輸出結果爲:(這裏以第一個url進行試錯,查看是否可以成功的返回請求的數據,只截取其中的一條信息)
在這裏插入圖片描述
3) 獲取需求字段信息

在試錯無誤後就可以或許需求的字段信息了,其中關於keywords字段信息的獲取這裏可以講一下,通過上面的輸出圖片可以發現,所有的信息都是以鍵值對的形式存儲,其他的字段信息都是爲字符串,而keywords字段信息是列表中嵌套着字典,因此要提取出裏面的keyname信息,還是需要點技巧的,代碼如下

for data in datas:
      dic = {}
      dic['title'] = data['title']
      dic['docurl'] = data['docurl']
      dic['commenturl'] = data['commenturl']
      dic['source'] = data['source']
      dic['time'] = data['time'].split(' ')[0]
      dic['keywords'] = ','.join(x['keyname'] for x in data['keywords'])
      count += 1
      #table.insert_one(dic)
      print(dic)

–> 輸出結果爲:(時間字段進行空格分隔,只選擇年月日即可,其他的字段直接可以選取,keywords字段信息需要先遍歷表格然後取出裏面的keyname信息,再將信息以逗號的形式組成字符串,這樣所有需要的字段信息都獲取完畢了,也可以添加一些其他的字段爬取信息,未防止審覈不通過,下面只截取部分結果)
HM6Ly9ibG9nLmNzZG4ubmV0L2x5c184Mjg=,size_16,color_FFFFFF,t_70)
4) 獲取全部數據並保存在數據庫

數據插入數據庫的操作就是一條指令table.insert_one(dic),打開上面的註釋即可,最後進行url的遍歷循環即可,爲了防止出錯,可以加上try-except進行異常處理

error_lst = []
count = 0
for u in urllst:
    try:
        count += get_data(urllst[0],dic_h,table)
        print(f'成功爬取並存儲{count}條數據')
    except :
        print('未能爬取數據網址爲:',u)
        error_lst.append(u)
6. 全部代碼及運行結果

如果要將結果數據

import pymongo
#import pandas as pd
import json,requests


def get_url(n):
    urllst = []
    url_fixed = 'https://temp.163.com/special/00804KVA/cm_yaowen20200213.js?callback=data_callback'
    urllst.append(url_fixed)
    urllst.extend([f'https://temp.163.com/special/00804KVA/cm_yaowen20200213_0{i}.js?callback=data_callback' for i in range(2,n+1)])
    # for i in range(2,n+1):
    #     urllst.append(f'https://temp.163.com/special/00804KVA/cm_yaowen20200213_0{i}.js?callback=data_callback')
    return urllst

get_url(5)


def get_data(url,dic_h,table):
    n = 0
    ri = requests.get(url,headers = dic_h)
    start = ri.text.index('[')
    end = ri.text.index('])') + 1
    datas = json.loads(ri.text[start:end])
    #data_lst = []
    for data in datas:
        dic = {}
        dic['title'] = data['title']
        dic['docurl'] = data['docurl']
        dic['commenturl'] = data['commenturl']
        dic['source'] = data['source']
        dic['time'] = data['time'].split(' ')[0]
        dic['keywords'] = ','.join(x['keyname'] for x in data['keywords'])
        table.insert_one(dic)
        n += 1
        #print(dic)
        #data_lst.append(dic)
    return n

if __name__ == '__main__':
    
    myclient = pymongo.MongoClient("mongodb://localhost:27017/")
    db = myclient['網易新聞']
    table = db['data1']

    urllst = get_url(5)
    dic_h = {'user-agent': 'Mozilla/5.0'}
    
    
    error_lst = []
    count = 0
    for u in urllst:
        try:
            count += get_data(urllst[0],dic_h,table)
            print(f'成功爬取並存儲{count}條數據')
        except :
            print('未能爬取數據網址爲:',u)
            error_lst.append(u)

–> 輸出結果爲:
在這裏插入圖片描述
生成桌面的文件如下:(截取部分)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章