API爬蟲--Twitter實戰

本篇將從實際例子出發,展現如何使用api爬取twitter的數據。java


1. 建立APP

進入https://apps.twitter.com/,建立本身的app。只有有了app才能夠訪問twitter的api並抓取數據。只需建立最簡單的app便可,各類信息隨意填寫,並不須要進一步的認證,咱們要的只是app的Consumer Key (API Key), Consumer Secret (API Secret), Access Token 和 Access Token Secret。鑑於單app的爬取次數限制,能夠申請不少app來提升總次數。數據庫


2. 肯定要使用的API

twitter提供多種類型的api,其中經常使用的有REST APIStreaming API。前者是常見的api類型,後者則能夠跟蹤監視一個用戶或者一個話題。api

REST API下面有不少的api,有價值爬取的有如下幾個:網絡

  • GET statuses/user_timeline:返回一個用戶發的推文。注意twitter裏回覆也至關於發推文。
  • GET friends/ids:返回一個用戶的followees。
  • GET followers/ids:返回一個用戶的followers。
  • GET users/show:返回一個用戶的信息。

3. 官方類庫

下載twitter的類庫。說實話,api爬蟲好很差寫,全看類庫提供的功能強不強。twitter提供了多種語言的類庫,本文選擇java類庫。app


4. 驗證受權

凡是訪問api,都須要驗證受權,也即:OAuth。通常流程爲:以app的id和key,用戶的用戶名和密碼爲參數訪問受權api,返回一個token(一個字符串),即算是受權完成,以後只需訪問其餘api時帶上這個參數就好了。框架

固然,不一樣的網站受權過程各有不一樣。較爲繁瑣的好比人人網須要先跳轉至回調網頁,用戶登錄後再返回token。twitter的受權過程也不簡單(須要屢次http請求),可是幸運的是類庫中已經幫咱們實現了此過程。ide

例,twitter的Auth1.1受權,其中須要設置的四個參數在app管理界面就能看到:網站

ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setOAuthAccessToken(accessToken); cb.setOAuthAccessTokenSecret(accessTokenSecret); cb.setOAuthConsumerKey(consumerKey); cb.setOAuthConsumerSecret(consumerSecret); OAuthAuthorization auth = new OAuthAuthorization(cb.build()); Twitter twitter = new TwitterFactory().getInstance(auth);

twitter還提供一種無需用戶受權(需app受權)的選擇,訪問某些api時可用次數比Auth1.1受權的要多:ui

ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setApplicationOnlyAuthEnabled(true); Twitter twitter = new TwitterFactory(cb.build()).getInstance(); twitter.setOAuthConsumer(consumerKey, consumerSecret); try { twitter.getOAuth2Token(); } catch (TwitterException e) { e.printStackTrace(); }

5. 調用API

受權以後,咱們就能夠真正地開始爬數據了。spa

  1. REST API

爬取用戶follower,getFollowersIDs方法每次返回最多5000個follower,cursor用戶標記從哪開始:

IDs iDs = twitter.getFollowersIDs(uid, cursor);

爬取用戶推文:

ResponseList<Status> status = twitter.getUserTimeline(uid, page);
  1. Streaming API

監視一個用戶的全部行爲,其中UserStreamListener太長了只截取了一部分:

TwitterStream twitterStream;
twitterStream = new TwitterStreamFactory(cb.build()).getInstance(); twitterStream.addListener(listener); twitterStream.user(); private static final UserStreamListener listener = new UserStreamListener() { @Override public void onStatus(Status status) { System.out.println("onStatus @" + status.getUser().getScreenName() + " - " + status.getText() + status.getCreatedAt()); } @Override public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) { System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId()); } @Override public void onDeletionNotice(long directMessageId, long userId) { System.out.println("Got a direct message deletion notice id:" + directMessageId); } @Override public void onTrackLimitationNotice(int numberOfLimitedStatuses) { System.out.println("Got a track limitation notice:" + numberOfLimitedStatuses); } @Override public void onScrubGeo(long userId, long upToStatusId) { System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId); } ...

6. 如何提速

api都是有訪問次數限制的,twitter中很多都是以15分鐘爲單位的。爲了爬取能達到必定的速度,我申請了50個app,只要pc給力,那麼我就有50倍於單app的速度了。

那麼我是單線程輪流用50個app仍是50個線程一塊兒呢?顯然50個線程不可行,一般20個線程以上的時候花費在線程同步上的時間就很可觀了,而且咱們寫的是爬蟲,50個線程同時寫數據庫會嚴重拖慢速度。那麼單線程呢?考慮到每一個app用完其訪問次數是須要必定時間的,特別要是網絡情況很差的話次數用完可能會花費數分鐘,那麼15分鐘顯然沒法讓每一個app都能訪問api,形成了浪費。

因此我選擇了線程池。IO密集型任務,通常將線程數設置爲cpu的核數的兩倍。同時設置兩個隊列,分別供各個線程讀取數據和寫數據。n個線程同時跑爬蟲,再分一個線程出來維護那兩個隊列。框架以下:

好了,到這裏應該能寫twitter的api爬蟲了。剩下的就是閱讀各個api繁瑣的文檔,以及和各類bug搏鬥的時間了╥﹏╥

相關文章
相關標籤/搜索