内容很简单就是使用htmlparser这个工具库来进行一些html的简单解析
测试页面:http://www.douban.com/people/maybedekky/notes
拦截的规则也是很简单的
- 豆瓣每页的url形式是http://www.douban.com/people/maybedekky/notes?start= 每页10页的话 第一页就是=0 第二页=10 以此类推
- 文章页面的url是http://www.douban.com/note/数字/ 的形式也很好获取到
- 然后就是文章内容 标题直接获取<title></title>就可以了 而内容则是被div class="note" id="link-report“包裹的
按照以上规则匹配就可以了
代码如下:
package org.cc.douban;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
/**
*
* @author fair_jm
* http://fair-jm.iteye.com/
*
*/
public class MayBeTest {
public static final int PAGE_SIZE = 10;
/**
* 如果输出的标题和内容是乱序的很正常 因为用了多线程在输出的时候也没加锁
* 可以放到数据库 或者生成文本 方法中并没有共享变量所以不会产生太大的问题
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
List<String> articel_urls = getUrl(
"http://www.douban.com/people/maybedekky/notes", 11);
Executor exec = Executors.newCachedThreadPool();
final CountDownLatch cdl = new CountDownLatch(articel_urls.size());
for (String url : articel_urls) {
final String u = url;
exec.execute(new Runnable() {
@Override
public void run() {
getArticle(u);
cdl.countDown();
}
});
}
cdl.await();
System.out.println("任务完成");
}
/**
* 得到文字(这里直接输出)
* @param url 文章的url
*/
public static void getArticle(String url) {
try {
Parser parser = new Parser(url);
parser.setEncoding("UTF-8");
NodeFilter articleFilter = new NodeFilter() {
public boolean accept(Node node) {
if (node.getText().startsWith(
"div class=\"note\" id=\"link-report\"")) {
return true;
} else {
return false;
}
}
};
NodeFilter titleFilter = new NodeFilter() {
public boolean accept(Node node) {
if (node.getText().startsWith("title")) {
return true;
} else {
return false;
}
}
};
OrFilter or1 = new OrFilter(new NodeFilter[] { articleFilter,
titleFilter });
NodeList list = parser.extractAllNodesThatMatch(or1);
for (int i = 0; i < list.size(); i++) {
Node tag = list.elementAt(i);
System.out.println(tag.getText() + "\n"
+ tag.getChildren().asString().trim() + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param url 要获取日志的地址
* @param pageCount 多少页
* @return 返回对应的url列表
*/
public static List<String> getUrl(String url, int pageCount) {
List<String> urls = new ArrayList<String>();
try {
for (int page = 0; page < pageCount; page++) {
Parser parser = new Parser(
url+"?start="
+ page * pageCount);
parser.setEncoding("gbk");
NodeList list = parser
.extractAllNodesThatMatch(new NodeClassFilter(
LinkTag.class));
for (int i = 0; i < list.size(); i++) {
Node tag = list.elementAt(i);
if (tag instanceof LinkTag)// <a> 标签
{
LinkTag link = (LinkTag) tag;
String linkUrl = link.getLink();// url
String text = link.getLinkText();// 链接文字
if (linkUrl.contains("http://www.douban.com/note")
&& linkUrl.endsWith("/")) {
if (!urls.contains(linkUrl)) {
urls.add(linkUrl);
}
}
}
}
}
} catch (ParserException e) {
e.printStackTrace();
}
for (String s : urls) {
System.out.println(s);
}
return urls;
}
}
输出就不写了 因为输出是乱序的(标题和内容我是分开打印的) 这个是没什么关系的 可以用写文件或者存入数据库的形式完成操作.