利用新浪API實現數據的抓取\微博數據爬取\微博爬蟲

PS:(本人長期出售超大量微博數據、旅遊網站評論數據,並提供各類指定數據爬取服務,Message to YuboonaZhang@Yahoo.com。因爲微博接口更新後限制增大,這個代碼已經不能用來爬數據了。若是隻是爲了收集數據能夠諮詢個人郵箱,若是是爲了學習爬蟲,建議改學phantomjs從網頁中爬取微博的)html

利用新浪API實現數據的抓取(因爲api接口限制增大,本文已基本廢棄)

<font color=#FF0000 size=4 face="黑體">
2018.5.16 提示
微博的api接口如今已經很差用了,普通權限的token已經爬不到什麼數據了,想要用這個代碼爬大量數據的已經不太可能,只能做爲熟悉微博api接口使用方法的一個小demo了。python

2018.4.16 說明linux

注意:今天有人言語惡劣地評論個人博客是垃圾,說個人代碼有問題,這篇博客歷史久遠,是我初玩爬蟲寫的博客。我很是感謝能對個人代碼提出意見的人,可是出言不遜,態度惡劣的人我是忍受不了的,有話好好說,是一個現代社會高學歷高知識分子的最低覺悟。ios

代碼我已經改過了,若是還有問題很是歡迎你們來溫和地指出!!!!git

同時,因爲新浪微博自己api機制的不斷更改,到目前爲止,這篇博客的內容已經有了侷限,對於我的開發者來講,你申請到的token的權限只能爬你本身的微博,因此對於想要靠api來爬數據的人,恐怕可能並不能達成本身的目的了。想要用api來爬取微博內容只能選擇獲取更高的開發者權限了。github

</font>web


1. 首先來看看最後咱們獲得的是什麼結果,是否是你想要了解的東西,再決定是否往下讀。 

註冊新浪微博
<br/>mongodb

我主要抓取了大概4天的數據,圖上能夠看的出來大概有360萬條數據,因爲是在本身的電腦上爬取作數據的,有時候晚上斷網了就間斷了,因此大概一天能夠爬取有100萬左右的最新微博數據(由於我調用的是最新的微博API public_timeline)數據庫

API文檔當中定義了不少返回的類型(以json數據格式返回,我選取了一些我認爲重要的信息抓取下來_如圖所示_: 大概有id號所在位置粉絲數,發的微博內容,發微博的時間等等。 固然這些數據均可以根據本身的須要進行定製。)json

大概就是這些內容,你若是認爲這對你有點幫助,就請繼續讀下去... 第一次寫博客有些囉嗦

2. 前期準備

咱們須要的東西:

  • 數據庫: mongodb(可使用客戶端MongoBooster)
  • 開發環境: Python2.7(我用的IDE是Pycharm)
  • 一個新浪開發者帳號: 用本身的新浪微博帳號註冊就行(後面會講)
  • 須要的庫: requests和pymongo(這些均可以在Pycharm中下載)

2.1 mongodb的安裝

MongoDB是一個高性能,開源,無模式的文檔型數據庫,是當前NoSql數據庫中比較熱門的一種。它在許多場景下可用於替代傳統的關係型數據庫或鍵/值存儲方式。Mongo使用C++開發。Mongo的官方網站地址是:http://www.mongodb.org/,讀者能夠在此得到更詳細的信息。

小插曲:什麼是NoSql?

  NoSql,全稱是 Not Only Sql,指的是非關係型的數據庫。下一代數據庫主要解決幾個要點:非關係型的、分佈式的、開源的、水平可擴展的。原始的目的是爲了大規模web應用,這場運動開始於2009年初,一般特性應用如:模式自由、支持簡易複製、簡單的API、最終的一致性(非ACID)、大容量數據等。NoSQL被咱們用得最多的當數key-value存儲,固然還有其餘的文檔型的、列存儲、圖型數據庫、xml數據庫等。

網上有不少安裝mongodb教程我就不寫了

Windows下mongodb的安裝

Linux下mongodb的安裝

2.2 新浪開發者帳號的註冊方法

  • 註冊新浪微博帳號(163郵箱、手機號)

註冊新浪微博

   建立完畢須要填寫手機號驗證
<br/>

sina
<br/>

sina
<br/>

sina

  • 點擊繼續建立

初次建立應用須要填寫以下信息:

sina

此頁面信息不須要填寫真實信息,如地區,電話,可隨意填寫。網站填https://www.baidu.com/便可。(郵箱要真實)

繼續建立應用。應用名稱自定義,平臺以下勾選 ios 、andrioid

sina

建立完畢直接返回繼續建立,一個帳號能夠建立10個應用,每一個應用對應一個access-token(事實上我只用了一個就能夠知足需求)

sina
<br/>

sina
<br/>

依次選取建立的應用。點sina將下方的token用txt保存便可。

  • 獲取key

回到

sina
<br/>

點擊個人應用

而後選擇本身剛剛建立的應用

sina

進入以後點擊應用信息

sina

保存下 APP Key 和 APP Secret

點擊高級信息

設置回調網址

sina

能夠設置成默認的
http://api.weibo.com/oauth2/d...

至此你的開發者帳號就已經完成了

2.3 依賴庫的安裝方法

requests和pymongo的安裝

能夠直接用pip安裝
pip install requests 和 pip install pymongo

也能夠在Pycharm裏面直接安裝

選擇File -> Settings -> Project -> Project Interpreter

能夠看到本身安裝的Python庫,點擊右邊的綠色 + 

安裝便可

3. 分析問題 

3.1 OAuth 認證

受權機制說明(很重要)

網上不少講利用新浪微博API發送微博什麼的都是使用的請求用戶受權Token這種方式,可是這種方式顯然不適用於咱們爬取數據,由於每次都要請求,每次都要從新獲取code。具體可參考新浪微博API的受權機制

廖雪峯老師(sinaweibopy 的貢獻者)也對這個受權機制有一個說明

經過新浪微博的API接入網站,因爲用戶無需在您的網站上註冊,就能夠直接?使用他/她在新浪微博的賬號和口令登陸您的網站,這就須要確保您的網站在無需知道,也不能知道用戶口令的狀況下確認用戶已經登陸成功。因爲用戶的口令存儲在新浪微博,所以,認證用戶的過程只能由新浪微博完成,但新浪微博如何與您的網站通訊並告知您用戶是否登陸成功呢?這個過程稱之爲第三方登陸,OAuth是一個標準的第三方登陸協議,藉助OAuth,您的網站就能夠安全地接入來自新浪微博登陸成功的用戶。

OAuth目前主要有1.0和2.0兩個版本,2.0版對1.0版作了大量簡化,API也更簡單。新浪微博最新的API也是採用的OAuth 2.0,整個登陸流程以下:

  1. 用戶在您的網站上點擊「使用新浪微博登陸」,您的網站將用戶重定向到新浪微博的OAuth認證頁,重定向連接中包含client_id參數做爲您的網站ID,redirect_uri參數告訴新浪微博當用戶登陸成功後,將瀏覽器重定向到您的網站;
  2. 用戶在新浪微博的認證頁輸入賬號和口令;
  3. 新浪微博認證成功後,將瀏覽器重定向到您的網站,並附上code參數;
  4. 您的網站經過code參數向新浪微博請求用戶的access token;
  5. 您的網站拿到用戶的access token後,用戶登陸完成。

OAuth的access token是提供認證服務的網站(例如新浪微博)生成的令牌,表明一個用戶認證信息。在隨後的API調用中,傳入該access token就表明這個登陸用戶,這樣,經過OAuth協議,您的網站將驗證用戶的步驟交給新浪微博完成,並由新浪微博告知您用戶是否登陸成功。

OAuth的安全性是經過步驟4完成的,經過code參數獲取access token的過程是您的網站後臺到新浪微博網站完成的,用戶沒法看到獲取access token的HTTP請求。若是用戶傳入僞造的code,則新浪微博會返回一個錯誤。

具體內容請看廖雪峯老師的文檔

大體上來講按照通常的請求用戶受權Token調用會出現這種狀況:

登陸微博
<br/>

獲取code
獲取code

登錄後會調轉到一個鏈接https://api.weibo.com/oauth2/...×××××××× 

咱們所須要的就是code=×××××××××× 的值

也就是說,每當你調用一次API認證在瀏覽器中都會出現一個code,這樣顯然不利於咱們去爬取網站 

怎麼解決問題呢?首先咱們想到的天然是在Python程序裏面模擬登陸新浪微博,而後天然能夠獲取到code的值,可是,模擬新浪微博登陸相對來講比較複雜,並且既然都模擬登陸成功了,爲啥還要調用API呢...直接自定義進行抓取不是更加方便。

若是看了上面的那個受權機制,就應該想到。這個時候就須要咱們以前申請的access-token了

access-token 根據個人理解就是把你的微博受權給了第三方讓他幫你作一些事情,相似於在你的手機端經過新浪微博來登陸而後進行操做(利用上面受權機制裏面講的一句話來講就是)_移動端應用可直接使用官方移動SDK,經過呼起微博客戶端(未安裝微博客戶端的會呼起H5受權頁)方式受權_

這個界面你應該很熟悉

新浪受權

新浪也給出了說明Oauth2/access token

4. 代碼實現 

有了token以後,實現抓取數據就十分簡單了
能抓取數據的多少就取決於你的token權限了

接下來就是利用API來獲取數據了:新建一個文件weibo_run.py

# -*- coding:utf-8 -*-
import requests
from pymongo import MongoClient

ACCESS_TOKEN = '2.00ZooSqFHAgn3D59864ee3170DLjNj'
URL = 'https://api.weibo.com/2/statuses/public_timeline.json'


def run():
#受權

    while True:
        #調用statuses__public_timeline的api接口
        params = {
            'access_token': ACCESS_TOKEN
        }

        statuses = requests.get(url=URL, params=params).json()['statuses']
        length = len(statuses)
        #這是後來我爲了查看獲取微博條數設置的
        print length

        #鏈接mongodb,不須要本地的額外配置
        Monclient = MongoClient('localhost', 27017)
        db = Monclient['Weibo']
        WeiboData = db['HadSelected']

        #獲取的各個數據名應該能夠清楚的看出來對應的是什麼數據
        for i in range(0, length):
            created_at = statuses[i]['created_at']
            id = statuses[i]['user']['id']
            province = statuses[i]['user']['province']
            city = statuses[i]['user']['city']
            followers_count = statuses[i]['user']['followers_count']
            friends_count = statuses[i]['user']['friends_count']
            statuses_count = statuses[i]['user']['statuses_count']
            url = statuses[i]['user']['url']
            geo = statuses[i]['geo']
            comments_count = statuses[i]['comments_count']
            reposts_count = statuses[i]['reposts_count']
            nickname = statuses[i]['user']['screen_name']
            desc = statuses[i]['user']['description']
            location = statuses[i]['user']['location']
            text = statuses[i]['text']

            #插入mongodb
            WeiboData.insert_one({
                'created_at': created_at,
                'id': id,
                'nickname': nickname,
                'text': text,
                'province': province,
                'location': location,
                'description': desc,
                'city': city,
                'followers_count': followers_count,
                'friends_count': friends_count,
                'statuses_count': statuses_count,
                'url': url,
                'geo': geo,
                'comments_count': comments_count,
                'reposts_count': reposts_count
                })

if __name__ == "__main__":
    run()

剛開始個人代碼是這樣的,看起來已經完成了。

可是,由於新浪會限制你的調用次數,後來我試了一下從新運行,結果發現了一個問題,我以前的_print length_ 出來的每行獲取值都不同,老是在16-20之間徘徊,這說明了我每次從新運行獲取的數據都不同.而後我想算了,乾脆寫個死循環看他何時再被封吧。因而代碼就變成了下面這樣

run()刪除,換成下面這個死循環。

if __name__ == "__main__":
    while 1:
       try:
           run()
        except:
            pass

結果他就一直運行下去了...運行了四天尚未被封,估計是封不了了...

其餘接口也是同樣使用,只用改變url和params就行,具體參數參照新浪微博API文檔

開始我發現一天能夠獲取800萬的數據,把我給樂的...後來發現好多好多重複的數據。最後找了半天的解決方案,在mongodb中根據用戶的id和建立的時間這兩點創建索引(由於一我的不可能在同一時刻發送兩條微博),最後沒有重複數據大概一天能夠獲取100萬條左右的信息。

我的博客

8aoy1.cn

相關文章
相關標籤/搜索