1. 程式人生 > >新浪微博爬蟲v1.0

新浪微博爬蟲v1.0

                 心血來潮想看看自己這幾年都去過什麼地方,因為我的動態資訊基本上都發布在微博上面的,上面也記錄了地址,我查看了一下,即使定位名稱顯示的籠統,但是定位了的都有較詳細的經緯度。於是就想做個爬蟲,把資料搞下來,然後弄到地圖上看看。因為工作基本上都在做Java,所以爬蟲也用Java寫了,等把爬蟲寫完善一點,再去試試別的語言吧。

                 以下是爬蟲採集程式,專案在我的GitHub上:https://github.com/callELPSYCONGROO/WeiboCrawler


一、 模擬登入

a)  登入分為幾個步驟:

     1)獲取登入請求地址及登入引數名稱
      這裡是通過http://weibo.cn/pub/手機版微博登入URL,獲取到登入地址。獲取到登入頁面之後,下載驗證碼,儲存到本地。
     2)傳送登入請求
      通過登入頁面獲取到的登入地址及引數,傳送到https://login.weibo.cn/login/,請求登入。

b) 

這裡使用了ApacheHttpComponents,主要使用了其中的幾個類:

i. HttpClient,這個類作用就相當於是客戶端,建立一個客戶端之後,執行其execute方法,向伺服器傳送請求。

ii. HttpGet/HttpPost,這兩個類是模擬Get/Post請求。

iii. HttpEntity,這個類儲存請求/相應所需引數。

c) 處理HTML格式資料,使用的是Jsoup,處理起來挺方便的。

 

二、 跳轉到需要查詢的頁面

a) 我的微博地址是:http://weibo.cn/2959779932/profile?vt=4

(隨便找的一個微博賬號),中間的數字因賬號而異,可從登入之後的頁面中抽取,想要爬取固定組的微博賬號,可以新建一個分組,從分組頁面中獲得索要爬取的賬號的微博首頁。

b) 登入一個賬號之後,查詢其他賬號(非登入的賬號),地址是:http://weibo.cn/u/2787081310?vt=4,若該帳號設定了個性域名,則地址為:http://weibo.cn/maemiiiiii?vt=4,後面的“maemiiiiii”即為使用者自己設定的域名。

 

三、 爬取微博

a) 得到微博頁面以後,每條微博都是由一個帶id屬性的<div>標籤所包括,取到這個標籤,就可以提取對應的資訊了。

b) 由於手機版的微博每次只顯示一張圖片,而且是一張縮圖,想要獲得微博原圖,需要進入“檢視原圖”去下載。


四、 資料庫

a)  資料庫使用的是Mysql5.7,這裡因為微博正文裡面會有emoji表情符,往資料庫中存的時候會報錯,所以,建立資料庫及表的時候,將字符集設定為utf8mb4格式,這種格式相容emoji。


五、 下載圖片

 

六、 存在問題

a) 沒有判斷訪問的頁面是否為正確的頁面。不知道用什麼方法去判斷是我訪問的那個頁面。假如要訪問http://sina.com/pub這個頁面,但是卻訪問到了http://sina.com/asd,兩個頁面都不會返回404之類的,如何去判斷呢?只能嚴格檢查訪問的URL

b) 基於問題a),使用者名稱和密碼必須填寫正確,否則爬取結果不正確。

c)    有一個字串問題比較疑惑,獲取到的微博釋出時間格式並不都是yyyy-MM-dd HH:mm:ss,還有這種MM月dd日 HH:


  

System.out.println("***"+"01-05 20:15 ".trim()+"****");
String d = "01-05 20:15 ".trim() + " ";
System.out.println("***"+d+"****");
d = d.substring(0, d.lastIndexOf(" "));
System.out.println("***"+d+"****");

這裡列印輸出為:


  

***01-05 20:15 ****
***01-05 20:15 ****
***01-05 20:15****

             字串 d 最後的一個空格,並未被trim()去掉,導致若用這個字串轉換成Date型別的話會報ParseException型別異常。使用d = d.substring(0, d.lastIndexOf(" "));這句在測試的時候可行(把尾部空格去掉),但是從頁面獲取到之後的字串使用這個方法卻去不掉空格。

            所以後來將字串String轉換為Date型別使用的方法都是:


  

String s = "2017-01-05 20:15 ";
Date d = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(s);
System.out.println("***"+d+"***");
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d));

            我猜測,trim()去不掉空格的原因是因為獲取到的字串最後一個看上去像空格的字元應該是個佔位符什麼的,現在的trim()方法(我使用的是JDK1.6)裡面沒有去掉那種格式符號的東西,所以才導致去不掉。(希望有人看到能幫我解惑)