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租房网房源信息采集爬虫相关推荐

  1. java房源信息管理的代码_crawler4j源码学习(2):Ziroom租房网房源信息采集爬虫

    /*** @date 2016年8月20日 下午6:13:24 *@version*@sinceJDK 1.8*/ public class ZiroomCrawler extendsWebCrawl ...

  2. 博通Broadcom SDK源码学习与开发12终结篇——TR069网管协议

    声明:原创作品,严禁用于商业目的. 本系列文章将全面剖析以Bcm33xxx芯片开发Cablemodem产品的SDK源码为例,从编译系统到各个功能模块进行分析与探讨. 文章目录 0.写在前篇 1. TR ...

  3. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  4. 博通Broadcom SDK源码学习与开发1——SDK源码探究与Cable Modem 系统编译

    声明:原创作品,严禁用于商业目的. 本系列文章将全面剖析以Bcm33xxx芯片开发Cablemodem产品的SDK源码为例,从编译系统到各个功能模块进行分析与探讨. 文章目录 0.写在前篇 1. 博通 ...

  5. clickhouse-jdbc 源码学习

    clickhouse-jdbc 源码学习 文章目录 clickhouse-jdbc 源码学习 包介绍 依赖版本 搭建环境版本如下 QA 1.LocalDate/LocalDateTime不兼容 2.一 ...

  6. 【Qt】通过QtCreator源码学习Qt(十二):Q_D和Q_Q指针(简称“d指针”)详解

    1.Q_D和Q_Q指针(简称"d指针")简介 参考博客: https://www.devbean.net/2016/11/qt-creator-source-study-07/ h ...

  7. Spring5.0源码学习系列之Spring AOP简述(九)

    前言介绍 附录:Spring源码学习专栏 在前面章节的学习中,我们对Spring框架的IOC实现源码有了一定的了解,接着本文继续学习Springframework一个核心的技术点AOP技术. 在学习S ...

  8. 蚂蚁金服开源-SofaRpc源码学习篇

    大家好,我叫大鸡腿,大家可以关注下我,会持续更新技术文章还有人生感悟,感谢~ 文章目录 官网 基本流程 SofaRpc学习 代码入手 服务端-发布过程 服务端-构造执行链 服务端-注册到注册中心 客户 ...

  9. Vue源码学习 - 组件化(三) 合并配置

    Vue源码学习 - 组件化(三) 合并配置 合并配置 外部调用场景 组件场景 总结 学习内容和文章内容来自 黄轶老师 黄轶老师的慕课网视频教程地址:<Vue.js2.0 源码揭秘>. 黄轶 ...

  10. 博通Broadcom SDK源码学习与开发3——Cable Modem Docsis3.0

    声明:原创作品,严禁用于商业目的. 本系列文章将全面剖析以Bcm33xxx芯片开发Cablemodem产品的SDK源码为例,从编译系统到各个功能模块进行分析与探讨. 文章目录 0.写在前篇 1. Ch ...

最新文章

  1. Linux自动化测试monkey,APP自动化测试中Monkey和 MonkeyRunner
  2. Apache的Rewrite规则详细介绍
  3. linux字符设备led驱动源码,字符设备驱动控制LED灯
  4. spring中事件发布设计与实现
  5. Cordova Embedded Server
  6. 关系数据库理论:数据库的六大范式知识笔记
  7. 用python下载辞典
  8. matlab qtdecomp,Opencv图像识别从零到精通(25)------区域分裂与合并
  9. b+树的增删改查_考研计算机 | 如何理解m阶B树?
  10. PX4模块设计之八:Ubuntu 20.04搭建FlightGear模拟器
  11. Vue源码分析之-源码下载和打包调试
  12. bigemap如何下生成CGCS2000坐标系等高线
  13. 百度自定义技能真机测试
  14. cadence SPB17.4 - Active Class and Subclass
  15. 网易云音乐的歌词无法在桌面歌词显示
  16. 【嵌入式Linux】学习路径
  17. 微信小程序实现画布各种手机尺寸自适应
  18. java推算日期后天_分别用C++和Java写的计算后天的日期code
  19. 【Web安全基础】PHP基础
  20. 朗读者李晓云清华大学计算机,世界杰出女科学家奖得主张弥曼现身《朗读者》...

热门文章

  1. linux怎么添加windows引导文件,Linux与Windows 10用grub引导教程
  2. css3中关于transform rotate、translate()、skew()、scale()的复合变换
  3. 从输入url到页面(二):TCP/IP 与 http协议
  4. PHP5 Session 使用详解(一)
  5. git and github secrets
  6. Eclipse(PHP、JAVA)的快捷键大全
  7. JavaScript版MD5应用
  8. WinForm PictureBox删除图片重新加载,显示System.IO.IOException:文件“**.png”正由另一进程使用,因此该进程无法访问此文件
  9. Vue报错: Maximum call stack size exceeded
  10. Jarslink Demo Alibaba(教程 源码)