爬蟲練習-爬取簡書網用戶動態信息(應對AJAX)

前言:

應對AJAX動態加載,爬取簡書網用戶動態信息,並將爬取的數據存儲於MongoDB數據庫中

本文爲整理代碼,梳理思路,驗證代碼有效性——2020.1.21


環境:
Python3(Anaconda3)
PyCharm
Chrome瀏覽器

主要模塊: 後跟括號內的爲在cmd窗口安裝的指令
requests(pip install requests)
lxml(pip install lxml)
pymongo(pip install pymongo )

1

首先簡單介紹一下異步加載(AJAX),它其實就是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。1

在網頁裏的體現如截圖所示,在點擊"文章"和點擊"動態"後,它們的網址url都沒有發生變化,這裏就是所謂的使用了異步加載(AJAX)。
在這裏插入圖片描述
在這裏插入圖片描述

2

那麼在爬蟲爬取信息時,我們要如何應對呢,打開開發者工具F12,切換至Network界面並選擇XHR文件,點擊一下動態,這時開發者工具界面應該如截圖所示,有一個名爲timeline?_pjax=%23list-container的文件生成,這就是第一步,找到動態文件,並獲取真實請求的URL(框起來了)。
在這裏插入圖片描述

3

這時我們要嘗試簡化刪除這個URL裏不必要的一些參數。

# 原URL
https://www.jianshu.com/users/c5a2ce84f60b/timeline?_pjax=%23list-container

# 精簡後
https://www.jianshu.com/users/c5a2ce84f60b/timeline

這樣我們就可以通過精簡後的URL構造其他的URL了。

4

當我們想找其他頁時,發現並沒有那種分頁條,簡書網的分頁也是通過異步加載實現的,那麼讓我們滑動頁面,看看加載了哪些文件。
在這裏插入圖片描述
這裏先異想天開的就留一個page的參數如:https://www.jianshu.com/users/c5a2ce84f60b/timeline?page=2,然而並沒有這麼簡單。
在這裏插入圖片描述
不錯,這裏是訪問到了界面,BUT,這個界面和第一頁的界面是一毛一樣啊/(ㄒoㄒ)/~~,說明另一個參數max_id也是一個重要參數,那麼接下來就考慮怎麼獲取max_id。

5

這裏需要一雙亮閃閃的大眼睛,我們通過各種尋找,發現了這些XHR文件中最後一個li元素標籤的id屬性值即爲下一頁的max_id+1。OK,順利解決問題。
在這裏插入圖片描述

6

之前的2-6步就是應對簡書網AJAX的方法,而該方法稱爲逆向工程方法。應對完這種‘反爬蟲’後,接下來的工作就是獲取信息並插入到MongoDB數據庫中。
我們需要爬取的信息爲動態類型(如下,“like_note”的意思爲“喜歡了文章”)及動態發佈時間。
在這裏插入圖片描述

7

這裏具體的網頁分析我就不多說了,詳見完整代碼,代碼相對簡單,而且我每塊都給註釋起來了,還有什麼無法理解的地方,評論請留言或私信我。

完整代碼

# url = "https://www.jianshu.com/users/c5a2ce84f60b/timeline?_pjax=%23list-container"
# 導入庫
import requests
from lxml import etree
import pymongo

# 連接MongoDB數據庫
client = pymongo.MongoClient('localhost', 27017)

# 創建數據庫和數據集合
mydb = client['mydb']
timeline = mydb['timeline']

# 加入請求頭
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}


def get_time_info(url, page):
    # 對url進行拆分,獲取用戶id,url如:https://www.jianshu.com/users/c5a2ce84f60b/timeline
    user_id = url.split('/')
    user_id = user_id[4]

    # 如果是第一頁後的url,其中會包含'page='的字樣,讓它進行翻頁
    if url.find('page='):
        page = page+1

    html = requests.get(url=url, headers=headers)
    selector = etree.HTML(html.text)
    print(url, html.status_code)

	# 首先將它分爲許多個li塊,方便後續解析數據
    infos = selector.xpath('//ul[@class="note-list"]/li')
    for info in infos:
        # 時間
        dd = info.xpath('div/div/div/span/@data-datetime')[0]
        # 動態類型
        type = info.xpath('div/div/div/span/@data-type')[0]
        
        # 以json或者說是字典的格式 插入數據
        timeline.insert_one({'date': dd, 'type': type})
        print({'date': dd, 'type': type})

    # 獲取id,以達到構造動態頁面的url的目的
    id_infos = selector.xpath('//ul[@class="note-list"]/li/@id')
    if len(infos) > 1:
        feed_id = id_infos[-1]
        # feed-id的原樣例如:feed-578127155,需手工切分
        max_id = feed_id.split('-')[1]
        # 構造動態頁面的url
        next_url = 'http://www.jianshu.com/users/%s/timeline?max_id=%s&page=%s' % (user_id, max_id, page)
        # 遞歸調用,爬取下一頁的信息
        get_time_info(next_url, page)


if __name__ == '__main__':
    get_time_info('https://www.jianshu.com/users/c5a2ce84f60b/timeline', 1)

  1. ajax (Ajax 開發) ↩︎

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