起因:本人特别喜欢看小说,网上有很多连载的小说。比如这样一个网站http://www.yi-see.com/art_5165_9215.html 下面是网站的截图:
一篇文章有很多小节,我想把所有的小节下下来,合并到一个文本文件中比如novel.txt。这样可以放在手机上,躺在被窝里看。于是写了这样一个小程序。这个小程序只是针对该网站的布局来写的,因此非常的不灵活。
这件事情看起来很复杂,首先需要从网站中把各个小节的超链接提取出来,然后连接每一个超链接,找到小说内容所在的标签,提取出内容下载到本地文件。每一项工作都很难实现,不像一个小程序能够完成的任务。但是因为有了她,一切都简单了。这就是牛逼的HTML分析库Jsoup。Jsoup接口做的非常的友好,大家一看就知道什么意思。
首先用Jsoup来实现提取各小节的网址的功能。共分三步
第一步:和网站建立连接,一句代码搞定。Document doc = Jsoup.connect(url).get();url为网站的网址。
第二步:提取所有的超链接地址,一句代码搞定。Elements links = doc.select("a[href]");这句代码的意思是把所有含有属性href的a标签提取出来。
第三步:在第二步中提取了所有的超链接,但是我们想要的是每一小节的超链接,下面就要对超链接进行筛选,通过观察网站的源代码,我们发现每一小节的地址都是以read开头,Jsoup牛逼的地方就体现出来了,它提供了通过正则表达式对元素进行筛选的功能。Elements links = doc.select("a[href~=read.*]");如果要跟正则表达式等号前面要加一个~符号。
下面就是提取出来的网址:
<read_83437_5165.html> (第1节)
<read_83440_5165.html> (第4节)
<read_83438_5165.html> (第2节)
<read_83441_5165.html> (第5节)
<read_83439_5165.html> (第3节)
<read_83442_5165.html> (第6节)
我们会发现,网址不是按顺序排列的,这样提取内容时,顺序也会发生问题,还需要对网址排序,排序很容易,见代码。
然后分析网页的结构找到小说内容所在的标签,会发现小说内容位于标签<td>中,而且该标签还有一个属性<td class=”ART”>提取小说内容也就非常简单了二句代码搞定。
text=doc2.select("td[class=ART]").first();
String str=text.html().replaceAll("<br />", "\r\n");
最后就是把内容保存到本地文件了非常简单,见代码
import org.jsoup.Jsoup; import org.jsoup.helper.Validate; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; import java.io.PrintWriter; public class JsoupTest { public static void main(String[] args) throws IOException { Validate.isTrue(args.length == 1, "usage: supply url to fetch"); String url = args[0]; PrintWriter output = new PrintWriter("F:/novel.txt","gb2312"); Document doc = Jsoup.connect(url).get(); Elements links = doc.select("a[href~=read.*]"); String stringLink[]=new String[288]; print("\nLinks: (%d)", links.size()); for (Element link : links) { String temp=link.text(); int index=Integer.valueOf(temp.substring(1, temp.length()-1)); stringLink[index]=link.attr("abs:href"); } Document doc2; Element text; for(int i=1;i<288;i++) { print("%s",stringLink[i]); doc2=Jsoup.connect(stringLink[i]).get(); text=doc2.select("td[class=ART]").first(); String str=text.html().replaceAll("<br />", "\r\n"); output.write(str); output.write("<--------------------------------------------------------------------->\n"); output.flush(); } }