java版web搜索爬虫系统,Java开源爬虫框架WebCollector教程——爬取搜索引擎

本教程演示了WebCollector 2.20的新特性。

下载

WebCollector最新jar包可在WebCollector github主页下载。

MetaData:

MetaData是每个爬取任务的附加信息,灵活应用MetaData可以大大简化爬虫的设计。

例如Post请求往往需要包含参数,而传统爬虫单纯使用URL来保存参数的方法不适合复杂的POST请求。

一些爬取任务希望获取遍历树的深度信息,这也可以通过MetaData轻松实现,

可参见教程DemoDepthCrawler。

RamCrawler:

RamCrawler不需要依赖文件系统或数据库,适合一次性的爬取任务。

如果希望编写长期任务,请使用BreadthCrawler。

本教程实现了一个爬取Bing搜索前n页结果的爬虫,爬虫的结果直接输出到标准输出流

如果希望将爬取结果输出到ArrayList等数据结构中,在类中定义一个ArrayList的成员变量,

输出时将结果插入ArrayList即可,这里需要注意的是爬虫是多线程的,而ArrayList不是线程

安全的,因此在执行插入操作时,可使用下面的方式上锁保证安全。

synchronized(this){

//插入操作

}

本教程中对Bing搜索的解析规则可能会随Bing搜索的改版而失效。

import cn.edu.hfut.dmic.webcollector.model.CrawlDatum;

import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;

import cn.edu.hfut.dmic.webcollector.model.Page;

import cn.edu.hfut.dmic.webcollector.plugin.ram.RamCrawler;

import java.net.URLEncoder;

import org.jsoup.select.Elements;

import org.jsoup.nodes.Element;

public class DemoBingCrawler extends RamCrawler {

public DemoBingCrawler(String keyword, int maxPageNum) throws Exception {

for (int pageNum = 1; pageNum <= maxPageNum; pageNum++) {

String url = createBingUrl(keyword, pageNum);

CrawlDatum datum = new CrawlDatum(url)

.type("searchEngine")

.meta("keyword", keyword)

.meta("pageNum", pageNum)

.meta("depth", 1);

addSeed(datum);

}

}

@Override

public void visit(Page page, CrawlDatums next) {

// 如果遇到301或者302,手动跳转(将任务加到next中)

// 并且复制任务的meta

if(page.code() == 301 || page.code() == 302){

next.addAndReturn(page.location()).meta(page.meta());

return;

}

String keyword = page.meta("keyword");

int pageNum = page.metaAsInt("pageNum");

int depth = page.metaAsInt("depth");

if (page.matchType("searchEngine")) {

System.out.println("成功抓取关键词" + keyword + "的第" + pageNum + "页搜索结果");

Elements results = page.select("li.b_algo>h2>a");

for (int rank = 0; rank < results.size(); rank++) {

Element result = results.get(rank);

/*

我们希望继续爬取每条搜索结果指向的网页,这里统称为外链。

我们希望在访问外链时仍然能够知道外链处于搜索引擎的第几页、第几条,

所以将页号和排序信息放入后续的CrawlDatum中,为了能够区分外链和

搜索引擎结果页面,type设置为outlink,这里的值完全由

用户定义,可以设置一个任意的值

*/

String href = result.attr("abs:href");

next.addAndReturn(href)

.type("outlink")

.meta("keyword", keyword)

.meta("pageNum", pageNum)

.meta("rank", rank);

}

} else if (page.matchType("outlink")) {

int rank = page.metaAsInt("rank");

String referer=page.meta("referer");

String line = String.format("第%s页第%s个结果:%s(%s字节)\tdepth=%s\treferer=%s",

pageNum, rank + 1, page.doc().title(),page.content().length,depth, referer);

System.out.println(line);

}

/*

在经典爬虫中,每个网页都有一个referer信息,表示当前网页的链接来源。

例如我们首先访问新浪首页,然后从新浪首页中解析出了新的新闻链接,

则这些网页的referer值都是新浪首页。WebCollector不直接保存referer值,

但我们可以通过下面的方式,将referer信息保存在metaData中,达到同样的效果。

经典爬虫中锚文本的存储也可以通过下面方式实现。

在一些需求中,希望得到当前页面在遍历树中的深度,利用metaData很容易实现

这个功能,在将CrawlDatum添加到next中时,将其depth设置为当前访问页面

的depth+1即可。

*/

next.meta("depth", depth + 1).meta("referer", page.url());

}

public static void main(String[] args) throws Exception {

DemoBingCrawler crawler = new DemoBingCrawler("网络爬虫", 3);

crawler.start();

}

/**

* 根据关键词和页号拼接Bing搜索对应的URL

* @param keyword 关键词

* @param pageNum 页号

* @return 对应的URL

* @throws Exception 异常

*/

public static String createBingUrl(String keyword, int pageNum) throws Exception {

int first = pageNum * 10 - 9;

keyword = URLEncoder.encode(keyword, "utf-8");

return String.format("http://cn.bing.com/search?q=%s&first=%s", keyword, first);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值