java要期末考試了,老師竟然說不考試卷,要我們寫程序來打分......我沒有一點點防備...言歸正傳,我準備寫一個百度貼吧爬蟲給他,爲了方便,使用jsoup來進行解析爬取。
用我們學校貼吧進行試驗(桂林理工大學吧),這個只是個簡單的試驗品,不喜勿噴。
使用jsoup來進行解析爬取。
- Document doc = Jsoup.connect("http://tieba.baidu.com/f?ie=utf-8&kw=%E9%83%91%E7%A7%80%E5%A6%8D")//桂工吧網址
- .userAgent( "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)")
- .timeout(3000) // 設置連接超時時間
- .get(); // 使用 GET 方法訪問 URL
用Chrome瀏覽器打開桂工吧官網,按下F12鍵,搜索一個帖子,如圖所示
<a href="/p/4201959797"我們要在總吧裏找到帖子的超鏈接,上面的"/p/4201959797"就是我們需要找的數據
用如下代碼就可以找到,Elements baiduPost=doc.select("a.j_th_tit");,a表示匹配<a>超鏈接標籤, .j_th_tit是標籤裏的類,所以doc.select(a.j_th_tit)的意思就是尋找所有<a>標籤裏有a.j_th_tit類的html
</pre><pre name="code" class="java"><span style="white-space:pre"> </span>Elements baiduPost=doc.select("a.j_th_tit");//總貼吧帖子url
System.out.println(baiduPost.attr("href"));
輸出如下(其實匹配了所有的出來,我這裏只輸出一個)
得到訪問的數據之後,貼吧都是http://tieba.baidu.com開頭,把匹配得到的url進行訪問。代碼如下
public static Document GetHtml(String url,int page) throws IOException {
//page 頁數 http://tieba.baidu.com/p/4201959797?pn=2
Document doc = Jsoup.connect("http://tieba.baidu.com"+url+"?pn="+page)
.userAgent(
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)")
.timeout(3000)
.get();
try {
Thread.sleep(3000);//暫停3秒,太快會被封ip
} catch (InterruptedException e) {
e.printStackTrace();
}
return doc;
}
這樣就進入帖子了,這裏我們只採集用戶名,信息和樓層
匹配標題,用getElementsByClass找到core_title_txt類,這個就是標題類了
Elements resultTitle=doc1.getElementsByClass("core_title_txt");//標題
內容和用戶名 Elements results=doc1.getElementsByClass("d_post_content_main");//內容所在的類的內容
Elements userName=doc1.getElementsByClass("icon");//用戶名所在的類的內容
for (int i = 0; i < results.size(); i++)
{
Element result = results.get(i);
Element links = result.getElementsByTag("div").get(0);//內容
Element username = userName.get(i);
Elements name = username.getElementsByTag("img");//用戶名
System.out.println(i+" "+" "+name.attr("username")+" "+links.text());
}
這裏基本上就可以爬出一個帖子頁面所有我們需要的內容了,當然有些帖子太長需要翻頁,那就還得找到帖子有多少頁,代碼如下
public static int GetPage(Document doc)
{
Elements resultPage=doc.getElementsByClass("l_reply_num");
Element result0 = resultPage.get(0);
Element result1=result0.getElementsByTag("span").get(1);
System.out.println(result1.text());
String number=result1.text();
int page = Integer.parseInt(number);//String轉換成int
return page;//返回頁數
}
好了,需要的東西都有了,設置循環就可以進行爬取了,總代嗎如下
Teste.java
package com.wuxin.main;
import java.io.IOException;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.wuxin.data.PostBar;
public class Teste{
public static void main(String[] args){
try {
int page=1;
Document doc=PostBar.GetHtml();//訪問總貼吧
Elements baiduPost=doc.select("a.j_th_tit");//總貼吧帖子url
System.out.println(baiduPost.attr("href"));
for(Element baidupost : baiduPost)
{
page=1;
System.out.println(baidupost.attr("href"));
Document doc0=Page.GetHtml(baidupost.attr("href"),page);//帖子的html
int wu =Page.GetPage(doc0);//帖子頁數
do {
Document doc1=Page.GetHtml(baidupost.attr("href"),page);
Elements resultTitle=doc1.getElementsByClass("core_title_txt");//標題
System.out.println("標題: "+resultTitle.text());
System.out.println("第"+page+"頁");
Elements results=doc1.getElementsByClass("d_post_content_main");//內容
Elements userName=doc1.getElementsByClass("icon");//用戶名
for (int i = 0; i < results.size(); i++)
{
Element result = results.get(i);
Element links = result.getElementsByTag("div").get(0);
Element username = userName.get(i);
Elements name = username.getElementsByTag("img");
System.out.println(i+" "+" "+name.attr("username")+" "+links.text());
}
} while ( wu!=page++);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Page.java
package com.wuxin.main;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class Page {
public static Document GetHtml(String url,int page) throws IOException {
Document doc = Jsoup.connect("http://tieba.baidu.com"+url+"?pn="+page)
.userAgent(
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)")
.timeout(3000)
.get();
try {
Thread.sleep(3000);//暫停3秒,太快會被封ip
} catch (InterruptedException e) {
e.printStackTrace();
}
return doc;
}
public static int GetPage(Document doc)
{
Elements resultPage=doc.getElementsByClass("l_reply_num");
Element result0 = resultPage.get(0);
Element result1=result0.getElementsByTag("span").get(1);
System.out.println(result1.text());
String number=result1.text();
int page = Integer.parseInt(number);//String轉換成int
return page;
}
}
PostBar.java
package com.wuxin.data;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class PostBar {
public static Document GetHtml() throws IOException
{
Document doc = Jsoup.connect("http://tieba.baidu.com/f?ie=utf-8&kw=%E9%83%91%E7%A7%80%E5%A6%8D")//想爬哪個吧就把這裏的url換掉
.userAgent(
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)")
.timeout(5000)
.get();
return doc;
}
}
運行結果如圖所示
代碼很簡單,只是簡單爬取了貼吧的3個屬性數據,如果大家還想要爬取圖片或者樓中樓之類的話自己去擴展實現吧,也不難的,也可以在這基礎之上進行優化爬取或者把數據存儲到數據庫(聽說現在大數據蠻值錢的,搞不好以後這些數據能賣錢呢哈哈哈)。
想爬取其他貼吧的話就把PostBar.java裏的訪問url換掉就行了,我測試了2個吧,都能爬。
PS:天冷了,人有點懶。所以這個爬蟲只能爬取總吧的前50個帖子,所以想爬更多的話就參考上面翻頁思路或者自己琢磨下怎麼翻頁吧