CSDN爬蟲(一)——爬蟲入門+數據總覽

CSDN爬蟲(一)——爬蟲入門+數據總覽

首先感謝webMagic的作者黃億華以及Jsoup的開發人員。

說明

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

博主信息抓取核心代碼預覽

    package com.wgyscsf.spider;

    import java.util.ArrayList;
    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 us.codecraft.webmagic.selector.Selectable;

    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 CsdnBlogAuthorSpider implements PageProcessor {
        private Site site = Site
                .me()
                .setDomain("blog.csdn.net")
                .setSleepTime(300)
                .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://blog.csdn.net/((?!/).)*$").match()) {
                /*
                 * header
                 */
                Selectable titleSelectable = page.getHtml().xpath(
                        "//div[@class=\"header\"]//div[@id=\"blog_title\"]");

                String blogUrl = titleSelectable.links().get();
                // 作者id
                String id_author = MyStringUtils.getLastSlantContent(blogUrl);
                // 博客標題
                String title = titleSelectable.xpath("//a//text()").get();
                // 描述
                String describe = titleSelectable.xpath("//h3//text()").get();

                /*
                 * 獲取個人資料模塊
                 */
                Selectable profileSelectable = page.getHtml().xpath(
                        "//ul[@class=\"panel_body profile\"]");
                // 獲取博主名字,打印結果可以看出不是博主名字,而是用戶id,這個應該是動態顯示的,還不能解決。
                String name = profileSelectable.xpath("//span/text()").toString();
                // 頭像
                String headImg = profileSelectable.xpath("//a//img/@src")
                        .toString();
                // System.out.println(headImg);
                /*
                 * 獲取個人成就模塊
                 */
                Selectable medalSelectable = profileSelectable
                        .xpath("//div[@id=\"blog_medal\"]");
                // 是否是博客專家
                boolean isBlogExpert = false;
                // 獲取其它頭銜
                boolean isColumnUp = false;
                boolean isPreBlogExpert = false;
                boolean isPersist = false;
                boolean isBlogStars = false;
                boolean isMicrMvp = false;

                // 是否是博客專家
                Selectable expert = medalSelectable
                        .xpath("//div[@class='ico_expert']//@title");
                if (expert.match())
                    if (expert.equals("CSDN認證專家")) {
                        isBlogExpert = true;
                    } else if (expert.equals("CSDN博客準專家")) {
                        isPreBlogExpert = true;
                    }
                // 頭銜模塊判斷
                Selectable selectable = medalSelectable
                        .xpath("//div[@id='bms_box']//a//img//@src");
                if (selectable.match()) {
                    List<String> honor = selectable.all();
                    List<String> mHonor = processHonor(honor);
                    // System.out.println(mHonor);
                    for (String string : mHonor) {
                        if (string.equals("zhuanlandaren.png"))
                            isColumnUp = true;
                        else if (string.equals("chizhiyiheng.png"))
                            isPersist = true;
                        else if (string.equals("bokezhixing.png"))
                            isBlogStars = true;
                        else if (string.equals("weiruanmvp.png"))
                            isMicrMvp = true;

                    }
                }

                /*
                 * 排名模塊
                 */
                Selectable rankSelectable = profileSelectable
                        .xpath("//ul[@id=\"blog_rank\"]");
                //以jsoup的方式進行解析
                Elements allElements = new Html(rankSelectable.get()).getDocument().getAllElements().get(0).getElementsByTag("li");
                // 瀏覽量
                String viewNums = allElements.get(0).getElementsByTag("span")
                        .text();
                viewNums = viewNums.substring(0, viewNums.length() - 1);
                // 積分
                String points = allElements.get(1).getElementsByTag("span")
                        .text();
                // 排名
                String rank = allElements.get(3).getElementsByTag("span").text();
                rank = MyStringUtils.getStringPureNumber(rank);

                /*
                 * 博客數量模塊
                 */
                Selectable statisSelectable = profileSelectable
                        .xpath("//ul[@id=\"blog_statistics\"]");
                // 以jsoup的方式進行解析
                Elements statisElements = new Html(statisSelectable.get())
                        .getDocument()
                        .getAllElements().get(0).getElementsByTag("li");
                // 原創量
                String originalNums = statisElements.get(0)
                        .getElementsByTag("span")
                        .text();
                originalNums = MyStringUtils.getStringPureNumber(originalNums);
                // 轉載量
                String repuishNums = statisElements.get(1).getElementsByTag("span")
                        .text();
                repuishNums = MyStringUtils.getStringPureNumber(repuishNums);
                // 譯文量
                String translateNums = statisElements.get(2)
                        .getElementsByTag("span")
                        .text();
                translateNums = MyStringUtils.getStringPureNumber(translateNums);
                // 評論量
                String commentNums = statisElements.get(3).getElementsByTag("span")
                        .text();
                commentNums = MyStringUtils.getStringPureNumber(commentNums);

                // 測試打印
                System.out.println("博主id:" + id_author + ",博客標題:" + title
                        + ",博客描述:" + describe + ",瀏覽量:" + viewNums + ",原創文章數:"
                        + originalNums + ",博客積分:" + points + ",(其它信息未打印)");


            }
        }

        /**
         * 獲取後綴名
         */
        private List<String> processHonor(List<String> honor) {
            List<String> str = new ArrayList<>();
            for (String string : honor) {
                str.add(MyStringUtils.getLastAfterSprit(string));
            }

            return str;
        }

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

        public static void main(String[] args) {
            Spider.create(new CsdnBlogAuthorSpider())

            .addUrl("http://blog.csdn.net/" + "wgyscsf")
                    .run();
        }

    }

關鍵代碼解釋

  • page.getUrl().regex("^http://blog.csdn.net/((?!/).)*$").match() 這句話是一個正則表達式,作用是過濾出以http://blog.csdn.net/開頭的網址,並且該網址後面不能再含有“/”這樣的字符。因爲我們觀察CSDN的博客會發現,在http://blog.csdn.net/後面緊跟的一串字符(數字+字母)就是用戶的id,不會再後其他“/”多更的信息。只要符合該規則都會進入到爬蟲隊列。
  • Selectable titleSelectable = page.getHtml().xpath("//div[@class=\"header\"]//div[@id=\"blog_title\"]");這句話是爲了獲取博客“頭部”的節點信息,裏面包含作者id、博客標題、博客描述等信息。
  • Elements allElements = new Html(rankSelectable.get()).getDocument().getAllElements().get(0).getElementsByTag("li");代碼中有大量的這樣類似的代碼,在webMagic中是沒有的,需要特別注意,這是jsoup風格的代碼,在jsoup中是以“節點”進行操作的,所有html元素全部以節點進行處理,有時候比較方便。new Html(rankSelectable.get()).getDocument().getAllElements()就是將webMagic處理的方式轉化爲了jsoup的方式進行處理的關鍵代碼。
  • .addPipeline(null)這代碼片段可以將控制檯打印的網址過濾掉。

數據預覽

  • CSDN用戶數據,跑了大致兩天的數據量
    這裏寫圖片描述
    這裏寫圖片描述
  • CSDN博主數據,剛開始
    這裏寫圖片描述
    這裏寫圖片描述
  • CSDN博數據,剛開始,電腦有點扛不住,數據量巨大
    這裏寫圖片描述
    這裏寫圖片描述

操作代碼及webMagic源碼下載

http://download.csdn.net/detail/wgyscsf/9644613

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

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