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