crawler4j:轻量级多线程网络爬虫实例
crawler4j是Java实现的开源网络爬虫。提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫。
下面实例结合jsoup(中文版API),javacvs 爬取自如租房网(http://sh.ziroom.com/z/nl/)租房信息。
1.maven导入相关包
<dependency>
<groupId>edu.uci.ics</groupId>
<artifactId>crawler4j</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>
2.创建自己的Crawler类 继承 WebCrawler
public class ZiroomCrawler extends WebCrawler {
/** 爬取数据保存文件路径 */
private final static String CSV_PATH = "data/crawl/ziroom.csv";
/** 爬取匹配原则 */
private final static Pattern FILTERS = Pattern.compile(".*(\\.(css|js|bmp|gif|jpe?g|ico"
+ "|png|tiff?|mid|mp2|mp3|mp4" + "|wav|avi|mov|mpeg|ram|m4v|pdf" + "|rm|smil|wmv|swf|wma|zip|rar|gz))$");
/** 爬取link文件路径 */
private final static String LINK_PATH = "data/crawl/link.csv";
private static final Logger logger = LoggerFactory.getLogger(ZiroomCrawler.class);
private final static String URL_PREFIX = "http://sh.ziroom.com/z/nl/";
private final File csv;
private final File csv2;
private CsvWriter cw;
private CsvWriter cw2;
/**
* You should implement this function to specify whether the given url
* should be crawled or not (based on your crawling logic).
*/
CrawlStat myCrawlStat;
public ZiroomCrawler() throws IOException {
myCrawlStat = new CrawlStat();
csv = new File(CSV_PATH);
csv2 = new File(LINK_PATH);
if (csv.isFile()) {
csv.delete();
}
if (csv2.isFile()) {
csv2.delete();
}
cw2 = new CsvWriter(new FileWriter(csv2, true), ',');
cw2.write("请求路径");
cw2.endRecord();
cw2.close();
cw = new CsvWriter(new FileWriter(csv, true), ',');
cw.write("图片");
cw.write("价格");
cw.write("地址");
cw.write("说明");
cw.endRecord();
cw.close();
}
public void dumpMyData() {
final int id = getMyId();
// You can configure the log to output to file
logger.info("Crawler {} > Processed Pages: {}", id, myCrawlStat.getTotalProcessedPages());
logger.info("Crawler {} > Total Links Found: {}", id, myCrawlStat.getTotalLinks());
logger.info("Crawler {} > Total Text Size: {}", id, myCrawlStat.getTotalTextSize());
}
@Override
public Object getMyLocalData() {
return myCrawlStat;
}
@Override
public void onBeforeExit() {
dumpMyData();
}
/*
* 这个方法决定了要抓取的URL及其内容,例子中只允许抓取“http://sh.ziroom.com/z/nl/”这个域的页面,
* 不允许.css、.js和多媒体等文件
*
* @see edu.uci.ics.crawler4j.crawler.WebCrawler#shouldVisit(edu.uci.ics.
* crawler4j.crawler.Page, edu.uci.ics.crawler4j.url.WebURL)
*/
@Override
public boolean shouldVisit(Page referringPage, WebURL url) {
final String href = url.getURL().toLowerCase();
if (FILTERS.matcher(href).matches() || !href.startsWith(URL_PREFIX)) {
return false;
}
return true;
}
/*
* 当URL下载完成会调用这个方法。你可以轻松获取下载页面的url, 文本, 链接, html,和唯一id等内容。
*
* @see
* edu.uci.ics.crawler4j.crawler.WebCrawler#visit(edu.uci.ics.crawler4j.
* crawler.Page)
*/
@Override
public void visit(Page page) {
final String url = page.getWebURL().getURL();
System.out.println("-----------爬取路径:" + url);
myCrawlStat.incProcessedPages();
if (page.getParseData() instanceof HtmlParseData) {
final HtmlParseData htmlParseData = (HtmlParseData) page.getParseData();
final Set<WebURL> links = htmlParseData.getOutgoingUrls();
try {
linkToCsv(links);
} catch (final IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
myCrawlStat.incTotalLinks(links.size());
try {
myCrawlStat.incTotalTextSize(htmlParseData.getText().getBytes("UTF-8").length);
} catch (final UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final String html = htmlParseData.getHtml();
final Document doc = Jsoup.parse(html);
final Elements contents = doc.select("li[class=clearfix]");
for (final Element c : contents) {
// 图片
final String img = c.select(".img img").first().attr("src");
System.out.println("图片:" + img);
// 地址
final Element txt = c.select("div[class=txt]").first();
final String arr1 = txt.select("h3 a").first().text();
final String arr2 = txt.select("h4 a").first().text();
final String arr3 = txt.select("div[class=detail]").first().text();
final String arr = arr1.concat(arr1 + ",").concat(arr2 + ",").concat(arr3);
System.out.println("地址:" + arr);
// 说明
final String rank = txt.select("p").first().text();
System.out.println("说明:" + rank);
// 价格
final String pirce = c.select("p[class=price]").first().text();
try {
cw = new CsvWriter(new FileWriter(csv, true), ',');
cw.write(img);
cw.write(pirce);
cw.write(arr);
cw.write(rank);
cw.endRecord();
cw.flush();
cw.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
}
private void linkToCsv(Set<WebURL> links) throws IOException {
cw2 = new CsvWriter(new FileWriter(csv2, true), ',');
for (final WebURL webURL : links) {
cw2.write(webURL.getURL());
}
cw2.flush();
cw2.endRecord();
cw2.close();
}
public class CrawlStat {
private long totalLinks;
private int totalProcessedPages;
private long totalTextSize;
public long getTotalLinks() {
return totalLinks;
}
public int getTotalProcessedPages() {
return totalProcessedPages;
}
public long getTotalTextSize() {
return totalTextSize;
}
public void incProcessedPages() {
this.totalProcessedPages++;
}
public void incTotalLinks(int count) {
this.totalLinks += count;
}
public void incTotalTextSize(int count) {
this.totalTextSize += count;
}
public void setTotalLinks(long totalLinks) {
this.totalLinks = totalLinks;
}
public void setTotalProcessedPages(int totalProcessedPages) {
this.totalProcessedPages = totalProcessedPages;
}
public void setTotalTextSize(long totalTextSize) {
this.totalTextSize = totalTextSize;
}
}
3.编写运行脚本的类
public class ZiroomController {
public static void main(String[] args) {
System.out.println("-------begin:" + new Timestamp(System.currentTimeMillis()));
final String crawlStorageFolder = "data/crawl/root";
final int numberOfCrawlers = 7;
final CrawlConfig config = new CrawlConfig();
config.setCrawlStorageFolder(crawlStorageFolder);
config.setPolitenessDelay(1000);
config.setIncludeBinaryContentInCrawling(false);
config.setMaxPagesToFetch(50);
// config.setResumableCrawling(true);
/*
* Instantiate the controller for this crawl.
*/
final PageFetcher pageFetcher = new PageFetcher(config);
final RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
final RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
CrawlController controller;
try {
controller = new CrawlController(config, pageFetcher, robotstxtServer);
/*
* For each crawl, you need to add some seed urls. These are the
* first URLs that are fetched and then the crawler starts following
* links which are found in these pages
*/
controller.addSeed("http://sh.ziroom.com/z/nl/");
// controller.addSeed("http://www.ziroom.com/z/nl/z3-u2.html/");
// controller.addSeed("http://www.ics.uci.edu/~welling/");
// controller.addSeed("http://www.ics.uci.edu/");
/*
* Start the crawl. This is a blocking operation, meaning that your
* code will reach the line after this only when crawling is
* finished.
*/
controller.start(ZiroomCrawler.class, numberOfCrawlers);
final List<Object> crawlersLocalData = controller.getCrawlersLocalData();
long totalLinks = 0;
long totalTextSize = 0;
int totalProcessedPages = 0;
for (final Object localData : crawlersLocalData) {
final CrawlStat stat = (CrawlStat) localData;
totalLinks += stat.getTotalLinks();
totalTextSize += stat.getTotalTextSize();
totalProcessedPages += stat.getTotalProcessedPages();
}
System.out.println("Aggregated Statistics:");
System.out.println("\tProcessed Pages: {}" + totalProcessedPages);
System.out.println("\tTotal Links found: {}" + totalLinks);
System.out.println("\tTotal Text Size: {}" + totalTextSize);
} catch (final Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
刚开始写博客 仅供参考!请多指教!
开源地址: https://github.com/yasserg/crawler4j
crawler4j:轻量级多线程网络爬虫实例的更多相关文章
- crawler4j:轻量级多线程网络爬虫
crawler4j是Java实现的开源网络爬虫.提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫. 安装 使用Maven 使用最新版本的crawler4j,在pom.xml中添加如下片段: ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...
- Python 利用Python编写简单网络爬虫实例3
利用Python编写简单网络爬虫实例3 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://bbs.51testing. ...
- Python 利用Python编写简单网络爬虫实例2
利用Python编写简单网络爬虫实例2 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://www.51testing. ...
- C# 多线程网络爬虫
原文 C#制作多线程处理强化版网络爬虫 上次做了一个帮公司妹子做了爬虫,不是很精致,这次公司项目里要用到,于是有做了一番修改,功能添加了网址图片采集,下载,线程处理界面网址图片下载等. 说说思路:首相 ...
- SHELL网络爬虫实例剖析--转载
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://nolinux.blog.51cto.com/4824967/1552472 前天 ...
- Python ===if while for语句 以及一个小小网络爬虫实例
if分支语句 >>> count=89 >>> if count==89: print count 89 #单分支 ...
- Pyhton网络爬虫实例_豆瓣电影排行榜_BeautifulSoup4方法爬取
-----------------------------------------------------------学无止境------------------------------------- ...
随机推荐
- CStdioFile
CStdioFile类的声明保存再afx.h头文件中. CStdioFile类继承自CFile类,CStdioFile对象表示一个用运行时的函数fopen打开的c运行时的流式文件.流式文件是被缓冲的, ...
- mysql中间件研究(Atlas,cobar,TDDL)
mysql-proxy是官方提供的mysql中间件产品可以实现负载平衡,读写分离,failover等,但其不支持大数据量的分库分表且性能较差.下面介绍几款能代替其的mysql开源中间件产品,Atlas ...
- DataTemplate和ControlTemplate的关系
DataTemplate和ControlTemplate的关系(转载自haiziguo) 一.ContentControl中的DataTemplate 在开始之前,我们先去看一下ContentCont ...
- 【转】Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android framework将会处理绘制过程,Activity只需提供它的布局的根节点. 绘制过程从布 ...
- 详解文件操作(ifstream、ofstream、fstream)[转]
C++ 通过以下几个类支持文件的输入输出: ofstream: 写操作(输出)的文件类 (由ostream引申而来) ifstream: 读操作(输入)的文件类(由istream引申而来) fstre ...
- C#委托的介绍(delegate、Action、Func、predicate)(转)
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 (1). delegate delegate我们常用到的一种声明 Deleg ...
- pat 1055 区间前k个
http://pat.zju.edu.cn/contests/pat-a-practise/1055 第二组数据比较大,如果单纯排序直接检索会超时,因为每次都是对所有数据进行遍历. N/200=500 ...
- Keil MDK AGDI Drivers, ULink, JLink, ST-Link, NuLink, JTAGjet
AGDI Drivers AGDI is an Application Program Interface (API) third-party developers can use to create ...
- 数据结构复习:希尔排序的C++实现
1.原理介绍 希尔排序又称为缩小增量排序,由D.L.Shell在1959年提出而得名. 该算法先取一个小于数据表中元素个数 n 的整数gap, 并以此作为第一个间隔,将数据分为gap个子序列,所有距离 ...
- poj 3635 Full Tank? ( 图上dp )
题意: 已知每一个点的加油站的油价单位价格(即点权).每条路的长度(边权). 有q个询问.每一个询问包含起点s.终点e和油箱容量. 问从起点走到终点的最小花费.假设不可达输出impossible,否则 ...