内容很简单就是使用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; } }