CSDN爬蟲(五)——CSDN用戶(所有)爬取+常用爬蟲正則整理

CSDN爬蟲(五)——CSDN用戶(所有)爬取+常用爬蟲正則整理

說明

  • 開發環境:jdk1.7+myeclipse10.7+win74bit+mysql5.5+webmagic0.5.2+jsoup1.7.2
  • 爬蟲框架:webMagic
  • 建議:建議首先閱讀webMagic的文檔,再查看此係列文章,便於理解,快速學習:http://webmagic.io/
  • 開發所需jar下載(不包括數據庫操作相關jar包):點我下載
  • 該系列文章會省略webMagic文檔已經講解過的相關知識。

概述

  • 我們會從CSDN個人中心出發,首先爬取一個用戶的個人信息。然後根據該用戶的好友關係去爬取好友信息。依次類推,爬取所用用戶。
  • 爬取CSDN所有用戶是根據“粉絲、關注”去爬取“粉絲、關注”,必然會涉及到“死循環”。到後期肯定會出現大量“髒數據”(重複數據),就要考慮到過濾髒數據的問題。
  • 雖然用webMagic框架爬蟲會用到大量的正則表達式,並且爬蟲類的正則在網上也很少能找到資料,但是也是比較固定。

CSDN用戶(所有)爬取代碼預覽

package com.wgyscsf.spider;

import java.util.List;

import org.jsoup.select.Elements;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;

import com.wgyscsf.utils.MyStringUtils;

/**
 * @author 高遠</n>
 * 編寫日期   2016-9-24下午7:25:36</n>
 * 郵箱  [email protected]</n>
 * 博客  http://blog.csdn.net/wgyscsf</n>
 * TODO</n>
 */
public class CsdnMineSpider implements PageProcessor {
    private final String TAG = CsdnMineSpider.class.getSimpleName();
    private Site site = Site
            .me()
            .setDomain("my.csdn.net")
            .setSleepTime(1000)
            // 便於測試,休眠較長時間。
            .setUserAgent(
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");

    @Override
    public void process(Page page) {
        // 列表頁: 這裏進行匹配,匹配出列表頁進行相關處理。
        if ((page.getUrl()).regex("http://my.csdn.net/\\w+").match()) {
            // 獲取最外層節點
            // TODO:應該是get(1),不知道爲什麼
            Elements mainElements = page.getHtml().getDocument()
                    .getElementsByTag("div").get(2).children();
            // 個人資料
            Elements profileElements = mainElements.get(0).getElementsByTag(
                    "div");
            // 個人技能
            Elements skillElements = mainElements.get(1)
                    .getElementsByTag("div");
            // 關係模塊:關注和被關注
            Elements relationElements = mainElements.get(2).getElementsByTag(
                    "div");

            // 獲取用戶id
            String id_mine = MyStringUtils.getLastSlantContent(skillElements
                    .get(0).getElementsByTag("a").get(0).attr("href"));
            // 開始獲取個人資料
            String headImg = profileElements.get(0)
                    .getElementsByClass("person-photo").get(0)
                    .getElementsByTag("img").attr("src");
            String fansNums = profileElements.get(0)
                    .getElementsByClass("fans_num").get(0)
                    .getElementsByTag("b").get(0).text();
            String nickname = profileElements.get(0)
                    .getElementsByClass("person-nick-name").get(0)
                    .getElementsByTag("span").get(0).text();
            // 這裏只能精確到個人資料,沒法繼續分,因爲好多用戶該欄目只填寫部分內容
            String personDetail = profileElements.get(0)
                    .getElementsByClass("person-detail").get(0).text();

            // 開始組織個人資料,保存數據操作
            System.out.println(TAG + ":用戶id:" + id_mine + ",暱稱:" + nickname
                    + ",粉絲:" + fansNums + ",個人資料概述:"
                    + personDetail + ",其它信息....");

            // 當前爬取頁面信息爬取結束,將當前頁面設置爲“跳過”,下次再加入爬蟲隊列,直接過濾,提高爬取效率。
            page.setSkip(true);
            // 測試,看是否再被爬取。
            page.addTargetRequest("http://my.csdn.net/wgyscsf");
            /*
             * 核心部分,從關係模塊出發,去遍歷所有相關用戶!
             */
            // 開始獲取關注與被關注以及訪客的個人中心。同時加入爬蟲隊列。
            String html = relationElements.get(0).html();
            List<String> all = new Html(html)
                    .xpath("//div[@class=\"mod_relations\"]").links().all();
            // 加入到爬蟲隊列
            page.addTargetRequests(all);

        }
    }

    @Override
    public Site getSite() {
        return site;
    }

    public static void main(String[] args) {
        Spider.create(new CsdnMineSpider())
                .addUrl("http://my.csdn.net/wgyscsf").thread(1)// 便於測試,只開一個線程,正常爬起來,可以開15不成問題。
                .pipeline(null)
                .run();
    }

}

關鍵代碼解釋

  • 正則 http://my.csdn.net/\\w+"表示過濾出以http://my.csdn.net/"開頭的網址鏈接。不過該正則存在一定的問題,就是隻對網址前面部分進行了限制,並沒有對後面進行限制。只要以http://my.csdn.net/"開頭的網址全部會被加入到爬蟲隊列,存在大量的“髒數據”網址。比較合理的是:http://my.csdn.net/"後面可以出現除了“/”的任意字符。正則的準確性直接影響到爬蟲的效率,越準確越好。這裏不再修改。
  • profileElements.get(0).getElementsByClass("person-detail").get(0).text();該代碼片段是爲了獲取用戶的個人資料,該資料比較多,包括行業、職業、地區(國、省、市、區等)、姓名等信息。經過分析沒有好的依據對信息進行歸類,這裏只是獲取粗略信息。經過分析,甚至說CSDN官方最開始對該塊沒有進行合理的安排,導致用戶的信息沒有統一的格式。
  • 以下代碼片段是該部分的核心代碼,實現了遞歸式的爬取所有用戶。relationElements元素來自於mainElements.get(2).getElementsByTag("div");,屬於“關係模塊”,包括關注的人和被關注的人以及訪客信息。在這個模塊中可以獲取部分其它用戶的id,只不過是部分的,最多隻有6個人信息。CSDN官方沒有提供獲取所有粉絲或者關注者的信息。不過,只要這僅僅的用戶信息,我們就可以爬取所有的用戶。方便的是,順便可以過濾掉“死魚”用戶(沒有相互關係的用戶)。

        // 開始獲取關注與被關注以及訪客的個人中心。同時加入爬蟲隊列。
        String html = relationElements.get(0).html();
        List<String> all = new Html(html)
                .xpath("//div[@class=\"mod_relations\"]").links().all();
        // 加入到爬蟲隊列
        page.addTargetRequests(all);
    
  • 需要說明的是,爬取所有用戶,其實不是一定要定位到“關係”模塊。我們甚至可以簡單粗暴的直接獲取http://my.csdn.net/user_id"中所用有效鏈接,直接加入到爬蟲隊列。到時候直接通過正則http://my.csdn.net/\\w+"過濾出有效鏈接即可。代碼如下:

        // 直接取出該網頁下的所有網址鏈接,簡單粗暴,不用進行判斷。
        // 只要在進入爬取用戶信息的時候加正則匹配即可。
        // 但是會出現過多的“髒數據”,增加判斷,影響爬取效率。
        List<String> all = page.getHtml().links().all();
        System.out.println(all);// 測試打印的網址鏈接
        // 加入到爬蟲隊列
        page.addTargetRequests(all);
    
  • 正如前文概述中所說,遞歸時的爬取用戶信息,會出現大量已經爬取過的頁面,我們需要“過濾”掉這些信息。核心的代碼是page.setSkip(true);,爬取之後,直接設置爲“跳過”,下次爬取會直接跳過該鏈接。webMagic的作者對該方法的解釋如下:

    /**

    • Set whether to skip the result.
    • Result which is skipped will not be processed by Pipeline.
      *
    • @param skip whether to skip the result
    • @return this
      */
  • 過濾代碼如下:

        // 當前爬取頁面信息爬取結束,將當前頁面設置爲“跳過”,下次再加入爬蟲隊列,直接過濾,提高爬取效率。
        page.setSkip(true);
        // 測試,看是否再被爬取。
        page.addTargetRequest("http://my.csdn.net/wgyscsf");
    

爬取結果預覽

  • 爬取所有用戶
    這裏寫圖片描述
  • 爬取所有http://my.csdn.net/user_id"內網址
    這裏寫圖片描述

常用爬蟲正則

  • http://my.csdn.net/\\w+" :過濾出所有以http://my.csdn.net/開頭的網址。
  • ^http://blog.csdn.net/((?!/).)*$:過濾出以http://blog.csdn.net/開頭,並且後面不能再出現“/”的所有網址鏈接。
  • ^http://blog.csdn.net/\\w+/article/list/[0-9]*[1-9][0-9]*$:過濾出http://blog.csdn.net/後面是任意字符,並且緊接着/article/list/,且/article/list/後面只能是數字的所有網址鏈接。
  • http://blog.csdn.net/\\w+/article/details/\\w+:效果同上,只是最後允許任意字符,不僅僅限於數字。

測試正則的方式

    Pattern pattern = Pattern
            .compile("^http://blog.csdn.net/\\w+/article/list/[0-9]*[1-9][0-9]*$");
    Matcher matcher = pattern
            .matcher("http://blog.csdn.net/wgyscsf/article/list/32423");
    boolean b = matcher.matches();
    // 當條件滿足時,將返回true,否則返回false
    System.out.println(b);

操作代碼(代碼已全部遷移至github,歡迎star)

https://github.com/scsfwgy/WebMagic_CSDN_Demo

個人公衆號,及時更新技術文章

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