crawler4j源码学习(2):Ziroom租房网房源信息采集爬虫
crawler4j是用Java实现的开源网络爬虫。提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫。下面实例结合jsoup解析网页,javacsv存储采集数据;采集自如ziroom租房网(http://sz.ziroom.com/z/nl/)的出租房信息。
所有的过程仅需两步完成:
第一步:开发Ziroom采集核心部分代码:
/**
* @date 2016年8月20日 下午6:13:24
* @version
* @since JDK 1.8
*/
public class ZiroomCrawler extends WebCrawler { /** 爬取匹配原则 */
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))$");
/** 爬取数据保存文件路径 */
private final static String DATA_PATH = "data/crawl/ziroom.csv";
/** 爬取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 fLinks;
private final File fDatas; private CsvWriter csvLinks;
private CsvWriter csvDatas; /**
* You should implement this function to specify whether the given url
* should be crawled or not (based on your crawling logic).
*/
ZiroomCrawlStat myCrawlStat; public ZiroomCrawler() throws IOException {
myCrawlStat = new ZiroomCrawlStat();
fLinks = new File(DATA_PATH);
fDatas = new File(LINK_PATH);
if (fLinks.isFile()) {
fLinks.delete();
}
if (fDatas.isFile()) {
fDatas.delete();
}
csvDatas = new CsvWriter(new FileWriter(fDatas, true), ',');
csvDatas.write("请求路径");
csvDatas.endRecord();
csvDatas.close();
csvLinks = new CsvWriter(new FileWriter(fLinks, true), ',');
csvLinks.write("图片");
csvLinks.write("价格");
csvLinks.write("地址");
csvLinks.write("说明");
csvLinks.endRecord();
csvLinks.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();
logger.info("爬取路径:" + 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");
logger.debug("图片:" + 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);
logger.debug("地址:" + arr);
// 说明
final String rank = txt.select("p").first().text();
logger.debug("说明:" + rank); // 价格
final String pirce = c.select("p[class=price]").first().text(); try {
csvLinks = new CsvWriter(new FileWriter(fLinks, true), ',');
csvLinks.write(img);
csvLinks.write(pirce);
csvLinks.write(arr);
csvLinks.write(rank);
csvLinks.endRecord();
csvLinks.flush();
csvLinks.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
} private void linkToCsv(Set<WebURL> links) throws IOException {
csvDatas = new CsvWriter(new FileWriter(fDatas, true), ',');
for (final WebURL webURL : links) {
csvDatas.write(webURL.getURL());
}
csvDatas.flush();
csvDatas.endRecord();
csvDatas.close();
}
}
第二步:开发Ziroom采集控制部分代码:
/**
* @date 2016年8月20日 下午6:15:01
* @version
* @since JDK 1.8
*/
public class ZiroomController { public static void main(String[] args) { final String crawlStorageFolder = "data/crawl/root";
final int numberOfCrawlers = 3; final CrawlConfig config = new CrawlConfig();
config.setCrawlStorageFolder(crawlStorageFolder);
config.setPolitenessDelay(1000);
config.setIncludeBinaryContentInCrawling(false);
config.setMaxPagesToFetch(50); 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); controller.addSeed("http://sh.ziroom.com/z/nl/"); 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 ZiroomCrawlStat stat = (ZiroomCrawlStat) 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();
}
}
}
第三步:开发Ziroom采集状态搜集代码:
/**
* @date 2016年8月20日 下午6:14:13
* @version
* @since JDK 1.8
*/
public class ZiroomCrawlStat {
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;
}
}
Ziroom采集数据展示:

crawler4j源码学习(2):Ziroom租房网房源信息采集爬虫的更多相关文章
- crawler4j源码学习(1):搜狐新闻网新闻标题采集爬虫
crawler4j是用Java实现的开源网络爬虫.提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫.下面实例结合jsoup,采集搜狐新闻网(http://news.sohu.com/)新闻标 ...
- NewBluePill源码学习
NewBluePill的源码也看的差不多了,一直说等有时间了再写学习的一些心得,拖来拖去弄到现在了,时间不是等来的,慢慢开始吧. 0x00 初识硬件虚拟化 硬件虚拟化对大数人来讲还是比较陌生. ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- NewBluePill源码学习 <一>
NewBluePill的源码也看的差不多了,一直说等有时间了再写学习的一些心得,拖来拖去弄到现在了,时间不是等来的,慢慢开始吧. 0x00 初识硬件虚拟化 硬件虚拟化对大数人来讲还是比较陌生. ...
- Vue源码学习二 ———— Vue原型对象包装
Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...
- SpringBoot源码学习系列之SpringMVC自动配置
目录 1.ContentNegotiatingViewResolver 2.静态资源 3.自动注册 Converter, GenericConverter, and Formatter beans. ...
- SpringBoot源码学习系列之嵌入式Servlet容器
目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...
- vue-elemnt-admin源码学习
vue-elemnt-admin源码学习 vue-element-admin是一个基于vue,element-ui的集成的管理后台.它的安装部分就不说了,按照官网的步骤一步步就可以执行了. https ...
随机推荐
- Learn ZYNQ (3)
移植android3.3到ZedBoard follow doc:Android移植Guide1.3.pdf follow website: http://elinux.org/Zedboard_An ...
- 词法分析器Antlr
一.我们都知道编程语言在执行之前需要先进行编译,这样就可以把代码转换成机器识别的语言,这个过程就是编译. 那么它是怎么编译的呢? Java在JVM虚拟机中进行编译,javascript在Js引擎中编译 ...
- Zabbix自带模板监控MySQL
先使用主机链接Mysql模板 . 然后写获取mysql状态的脚本,即配合zabbix模板里面的参数的脚本. #!/bin/bash MYSQL_USER='zabbix' #这里为在本地数据库授权的账 ...
- js实现时钟
<!DOCTYPE html> <html> <head> <title>Js版带表盘的时钟</title> <meta charse ...
- mongodb 安装后 出现警告:** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000
警告问题:当前mongodb 支持的最大文件数有256个,但是推荐至少1024个. 解决办法: 1.关闭现在打开的mongodb 终端窗口 2.重新打开终端并运行一下命令: sudo launchct ...
- spring和mybatis集成,自动生成model、mapper,增加mybatis分页功能
软件简介 Spring是一个流行的控制反转(IoC)和面向切面(AOP)的容器框架,在java webapp开发中使用广泛.http://projects.spring.io/spring-frame ...
- iostat监控磁盘io
1.安装#yum install sysstat 2.启动#/etc/init.d/sysstat start 3.自启动#checkfig sysstat 4.基本使用#iostat -k 2每两秒 ...
- [daily][troubleshoot][archlinux][wps][font] wps文档中的图内容无法显示中文
序 用linux作为工作生产环境的几个需要解决的问题之一是:文档协作,即如何兼容Micro$oft Office格式的文档. 我一般的工作方式是:在linux下创建一个win7的虚拟机,安装常用的wi ...
- 欢快的使用Unity JSON吧
0x01:前言 Unity 5.3加入了UnityUtility类,意味着Unity终于有了自己原生态的JSON库.Unity主要用来游戏开发,JSON做为游戏开发中最受欢迎的配置文件.在官方没有库支 ...
- C#中的延迟加载
什么是延迟加载? 延迟加载顾名思义就是:推迟加载的时机,当真正使用的时候才加载. 通常在创建一个大对象时,有些属性我们可以在使用到的时候才去创建(设置属性的值),这个可以有效的提升系统性能. 示例 ...