您的位置:首页 > 理论基础 > 计算机网络

网络采集器Demo:Jsoup+Java多线程实现[爬虫](上)

2015-11-01 00:01 274 查看
ailab-mltk:/article/8137889.html

里面最简单,但是很常用的一个部分,就是网络爬虫,从网页上获取文本信息

这里用到两个工具,一个就是Java多线程(基于Java5 以上的线程池模式,区别于过时的Runable),另外一个是一个小工具:Jsoup,用于解析html网页,获取其中的内容,关于Jsoup的使用,这是一个技术活,在下面的描述中会介绍一些基础操作,但主要还是需要师弟们自己去学习:http://www.open-open.com/jsoup/

demo的功能是,爬取新浪主页的新闻文本内容。

下面我们一步一步来:

新浪首页即是我们的种子页面,首先我们需要获取新浪首页上的全部内容链接

1.用Jsoup获得种子页面的html代码

public class JsoupGetDocument {

public static Document getDocumentByJsoupBasic(String url) {
try {

// 设置连接超时和读数超时
// 设置忽略过期页面
return Jsoup.connect(url).timeout(120000).ignoreHttpErrors(true)
.ignoreContentType(true).get();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();

return null;
}
}
}
第7行解释:链接到要获取html代码的url,设置等待时间,忽略http错误,忽略网页内容编码格式

返回的是Jsoup中的Docment对象,内包含html代码以及其结构信息,它可以用作我们进一步对获取的html代码分析。

2.获得种子页面上的全部有效链接

public class FetchLinksFromPage {

// 获得所有的链接
public Set<ExactLinks> getAllUrl(String seedUrl) {
Set<ExactLinks> urlSet = new HashSet<ExactLinks>();

try {
Document docPage = JsoupGetDocument
.getDocumentByJsoupBasic(seedUrl);
Elements eleLinks = docPage.select("a[href]");
for (Element eleLink : eleLinks) {
String url = eleLink.attr("abs:href");
String urlMD5 = new TransMD5().getMD5Code(url);

urlSet.add(new ExactLinks(url, urlMD5));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return urlSet;
}

// 过滤出有用的url
public Set<ExactLinks> filterUrl(String seedUrl) {

Set<ExactLinks> urlSet = this.getAllUrl(seedUrl);
Set<ExactLinks> filterLinks = new HashSet<ExactLinks>();

for (String urlModel : CrawlUnitParam.SINA_URL_MODEL) {

for (ExactLinks links : urlSet) {
if (links.getUrl().contains(urlModel)) {
filterLinks.add(links);
}
}
}

return filterLinks;
}
}
第8行获得页面Docment对象后,第10行获得全部带有链接信息的元素块,这里Elements对象是一个集合,其中每一个Element都是单独一个含有链接的html子块,这里要注意,select方法是Jsoup精髓,传入的参数是一个匹配html代码位置的模式串,关于这个模式串的设计,就是之前说的技术活,学习:http://www.open-open.com/jsoup/selector-syntax.htm。下面的循环是对每个子块中的链接元素进行提取,并加入结果集合。

getAllUrl返回的是种子页面上全部锚链接的集合,注意这个集合用的是HashSet,可以自动排除重复的链接,可以自己设计一个ExactLinks类,需要重写hashCode和equals函数。但是,到这一步并没有结束,filterUrl方法是为了过滤无用的链接,CrawlUnitParam.SINA_URL_MODEL中存储的是有用链接的模式集合,可以自己设计,匹配成功才加入最终的集合,并返回。我的模式集合是:

public class CrawlUnitParam {

public static List<String> SINA_URL_MODEL = new ArrayList<String>();
static {
SINA_URL_MODEL.add(".shtml");
SINA_URL_MODEL.add(".html");
}
}
可以自己打印一下解析出来的全部链接。

3.解析获得每个链接中的文本内容

我们将上面的每个链接传入函数getParagraphContent,返回该页中有效的文本内容

public class FetchPaContentFromPage {

public String getParagraphContent(String pageUrl) {

String paragraphContent = "";

try {
Document docPage = JsoupGetDocument
.getDocumentByJsoupBasic(pageUrl);
Elements eleParagraphs = docPage.select("p");
for (Element eleParagraph : eleParagraphs) {
String content = eleParagraph.text();

paragraphContent += content;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();

return null;
}

return paragraphContent;
}
}
同样在第8行获得页面的Docment对象之后,下面就是对包含有效文本的html子块进行抽取,还是使用select方法,至于什么是有效的文本信息,这些内容包含在具有什么特点的html子块中,需要我们分析网站页面的html代码,新浪新闻的有效信息就包含在<p></p>子块中,于是我们如上进行抽取。

下面循环中的text方法是获得html代码子块中包含的文本信息,对所有这样的文本信息进行拼接,返回。

好了,经过以上的步骤,相信师弟们自己完成一个串行的采集器没有问题了吧,但是我并没有那样实现,下一节将描述一个并行实现的采集器,这样我们会获得更高的效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: