需求:采集网站中每一页的联系人信息

一、创建maven工程,添加jsoup和poi的依赖包

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16-beta2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>

二、发送http get请求的客户端类

  这里简单使用Jsoup.connect()访问url,也可以用HttpClient创建一个connection,设置长连接Connection:keep-alive,全部页面访问完成后再关闭connection,效率更高

package com.guods.contact;

import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; /**
* 这里简单使用Jsoup.connect()访问url
* 扩展:也可以创建一个connection,设置长连接Connection:keep-alive,全部页面访问完成后再关闭connection,效率更高
* @author guods
*
*/
public class MyHttpClient { public Document get(String url){
try {
return Jsoup.connect(url)
.get();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

三、excel存取类,解析页面时提取联系人信息,存入excel文档。

package com.guods.contact;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; /**
* excel
*
* @author guods
* 扩展:excel读写数据可以模仿集合实现增删改查等方法,方便调用
* 如,把本类实现Iterable接口,再写个实现Iterator的内部类,就可以和集合一样迭代excel每一行的数据,这里用不到暂且不写
*/
public class Excel { private String filePath;
private XSSFWorkbook workbook;
private XSSFSheet sheet;
private XSSFCellStyle titleStyle, commonStyle;
private int rowCount; //总记录数 /**
*
* @param file 文件名
* @param sheetName sheet名
* @param columnNames 第一行内容(标题)
*/
public Excel(String file, String sheetName, String[] columnNames) {
super();
this.filePath = file;
newSheet(sheetName, columnNames);
}
/**
* 初始化excel表格,生成标题(第一行数据)
* @param sheetName sheet标签名
* @param columnNames 列名
*/
private void newSheet(String sheetName, String[] columnNames){
workbook = new XSSFWorkbook();
//设置标题字体
XSSFFont titleFont = workbook.createFont();
titleFont.setBold(true);
titleFont.setFontName("黑体");
titleStyle = workbook.createCellStyle();
titleStyle.setFont(titleFont);
//设置正文字体
XSSFFont commonFont = workbook.createFont();
commonFont.setBold(false);
commonFont.setFontName("宋体");
commonStyle = workbook.createCellStyle();
commonStyle.setFont(commonFont);
//创建sheet
sheet = workbook.createSheet(sheetName);
//设置初始记录行数
rowCount = 0;
//创建标题行
insertRow(columnNames, titleStyle);
}
public void insertRow(String[] rowData){
insertRow(rowData, commonStyle);
}
/**
* 插入一行数据
* @param rowData 数据内容
* @param style 字体风格
*/
public void insertRow(String[] rowData, XSSFCellStyle style){
XSSFRow row = sheet.createRow(rowCount);
for (int i = 0; i < rowData.length; i++) {
XSSFCell cell = row.createCell(i);
sheet.setColumnWidth(i, 5000);
cell.setCellStyle(style);
cell.setCellValue(rowData[i]);
}
rowCount++;
}
/**
* excel文件存储到磁盘
*/
public void saveFile(){
try {
File file = new File(filePath);
if (file.exists()) {
file.delete();
}
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
workbook.write(fileOutputStream);
} catch (FileNotFoundException e) {
System.out.println(filePath + "保存文件错误:" + e.getMessage());
} catch (IOException e) {
System.out.println(filePath + "保存文件错误:" + e.getMessage());
}
}
/**
* 返回excel总行数
* @return
*/
public int size() {
return rowCount;
} }

四、页面解析类。解析MyHttpClient获取的页面,把有效数据存到excel。

  分析html页面的标签结构,根据标签结构写页面的解析方法,取联系人信息对应的元素。

  当然,如果采集的量比较多的话也可以把数据存到本地数据库作为自己的联系人库。方便起见先存到excel。

package com.guods.contact;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; public class PageParser { /**
* 解析列表页面,根据页面的标签结构提取联系人信息
* VIP会员在列表中没有展示联系人信息,需要获取VIP会员的公司链接,抓取公司页面,在公司页面获取联系人信息
* @param document 获取的http页面
* @param excel 提取客户信息存到excel
*/
public void parseListPage(Document document, Excel excel){
if (document == null) {
return;
}
Elements tbodys = document.getElementsByTag("tbody");
if (tbodys == null || tbodys.size() == 0) {
return;
}
Element tbody = tbodys.get(0);
Elements trs = tbody.getElementsByTag("tr");
for (int i = 0; i < trs.size(); i++) {
//解析列表页面,获取列表信息
Elements tdivs = trs.get(i).getElementsByClass("tdiv");
if (tdivs.size() == 0) {
continue;
}
//取描述字段
Element tdiv = trs.get(i).getElementsByClass("tdiv").get(0);
String desc = tdiv.text();
//取标题字段
Element a = tdiv.getElementsByTag("a").get(0);
String title = a.text();
//取客户名字段
Element seller = tdiv.getElementsByClass("seller").get(0);
String sellerName = seller.text();
//取联系电话字段
Element yuyueVertop = trs.get(i).getElementsByClass("yuyue_vertop").get(0);
String contact = yuyueVertop.attr("data-j4fe");
//excel插入记录,联系电话没有的数据不记录
if (contact != null && contact.trim() != "") {
String[] rowData = {title, desc, sellerName, contact};
excel.insertRow(rowData);
}
}
} }

五、采集数据

  浏览器上复制页面的url,以url的页码数为界前后分开,把preUrl + 页码数 + postUrl拼接成完整的url,循环访问每个页面。

package com.guods.contact;

import org.jsoup.nodes.Document;

public class Main
{
public static void main( String[] args )
{
//采集1-10页的数据
startWork(1, 10);
} public static void startWork(int fromPage, int endPage){
StringBuffer urlBuffer = new StringBuffer();
String preUrl = "http://hz.58.com/shigongjl/pn";
String postUrl = "/?PGTID=0d306d36-0004-f163-ca53-0cdfddb146d0&ClickID=2";
MyHttpClient myHttpClient = new MyHttpClient();
Document document;
//创建excel文档
String[] columnNames = {"标题", "描述", "名字", "联系方式"};
Excel excel = new Excel("d:\\contact.xlsx", "contact", columnNames);
//创建一个解析器
PageParser parser = new PageParser();
//修改页码拼接请求,一次循环处理一个页面
for (int i = fromPage; i <= endPage; i++) {
//清空urlBuffer,重新组装url
if (urlBuffer.capacity() > 0) {
urlBuffer.delete(0, urlBuffer.capacity());
}
urlBuffer.append(preUrl).append(i).append(postUrl);
//访问url,获取document
document = myHttpClient.get(urlBuffer.toString());
//解析document
parser.parseListPage(document, excel);
System.out.println("第" + i + "页列表采集完成。。。");
}
//数据存档
excel.saveFile();
System.out.println("采集完成,列表总共:" + excel.size() + "条");
}
}

六、运行结果:

第1页列表采集完成。。。
第2页列表采集完成。。。
第3页列表采集完成。。。
第4页列表采集完成。。。
第5页列表采集完成。。。
第6页列表采集完成。。。
第7页列表采集完成。。。
第8页列表采集完成。。。
第9页列表采集完成。。。
第10页列表采集完成。。。
采集完成,列表总共:317条

第一次发博,亲测可用。

源码下载:https://github.com/dongsheng824/guods.git

Jsoup抓取、解析网页和poi存取excel综合案例——采集网站的联系人信息的更多相关文章

  1. 使用java开源工具httpClient及jsoup抓取解析网页数据

    今天做项目的时候遇到这样一个需求,需要在网页上展示今日黄历信息,数据格式如下 公历时间:2016年04月11日 星期一 农历时间:猴年三月初五 天干地支:丙申年 壬辰月 癸亥日 宜:求子 祈福 开光 ...

  2. jsoup抓取网页+具体解说

    jsoup抓取网页+具体解说 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目.我以前在 IBM DW 上发表过两篇关于 htmlparser 的文章.各自 ...

  3. Jsoup抓取网页数据完成一个简易的Android新闻APP

    前言:作为一个篮球迷,每天必刷NBA新闻.用了那么多新闻APP,就想自己能不能也做个简易的新闻APP.于是便使用Jsoup抓取了虎扑NBA新闻的数据,完成了一个简易的新闻APP.虽然没什么技术含量,但 ...

  4. HttpClients+Jsoup抓取笔趣阁小说,并保存到本地TXT文件

    前言 首先先介绍一下Jsoup:(摘自官网) jsoup is a Java library for working with real-world HTML. It provides a very ...

  5. 抓取https网页时,报错sun.security.validator.ValidatorException: PKIX path building failed 解决办法

    抓取https网页时,报错sun.security.validator.ValidatorException: PKIX path building failed 解决办法 原因是https证书问题, ...

  6. python网络爬虫抓取动态网页并将数据存入数据库MySQL

    简述以下的代码是使用python实现的网络爬虫,抓取动态网页 http://hb.qq.com/baoliao/ .此网页中的最新.精华下面的内容是由JavaScript动态生成的.审查网页元素与网页 ...

  7. 【转】详解抓取网站,模拟登陆,抓取动态网页的原理和实现(Python,C#等)

    转自:http://www.crifan.com/files/doc/docbook/web_scrape_emulate_login/release/html/web_scrape_emulate_ ...

  8. jsoup抓取网页内容

    java项目有时候我们需要别人网页上的数据,怎么办?我们可以借助第三方架包jsou来实现,jsoup的中文文档,那怎么具体的实现呢?那就跟我一步一步来吧 最先肯定是要准备好这个第三方架包啦,下载地址, ...

  9. selenium抓取动态网页数据

    1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...

随机推荐

  1. Java线程池ExecutorService

    开篇前,我们先来看看不使用线程池的情况: new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override ...

  2. 好多鱼 Java

    牛客网的题目: 链接:https://www.nowcoder.com/questionTerminal/e3dd485dd23a42899228305658457927牛牛有一个鱼缸.鱼缸里面已经有 ...

  3. java 学习资源

    1.tomcat版本http://tomcat.apache.org/whichversion.html 2.Servlet 2.5规范https://jcp.org/aboutJava/commun ...

  4. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  5. 【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  6. [LeetCode] 01 Matrix 题解

    题意 # 思路 我一开始的时候想的是嘴 # 实现 ```cpp // // include "../PreLoad.h" class Solution { public: /** ...

  7. 给angularJs grid列上添加自定义按钮

    由于项目需要在angular 显示的表格中添加按钮,多次查询资料终于找到解决方法.就是给columnDefs 上的列增加 cellTemplate,同时绑定对应的触发事件,代码如下 columnDef ...

  8. Spark2.1.0分布式集群安装

    一.依赖文件安装 1.1 JDK 参见博文:http://www.cnblogs.com/liugh/p/6623530.html 1.2 Hadoop 参见博文:http://www.cnblogs ...

  9. 转:java实例化对象的过程

    学习JAVA这门面向对象的语言,实质就是不断地创建类,并把类实例化为对象并调用方法.对于初学JAVA的人总搞清楚对象是如何实例化的,假如类之间存在继承关系,那就更糊涂了.下面我们通过两个例题来说明对象 ...

  10. loadrunner提高篇-插入检查点与关联函数

    插入检查点   靠LR自动生成的脚本是不够的,很难达到业务要求,因此需要对录制完的脚本进行完善,使其能达到业务模拟的要求 ,这样尽可能地使虚拟用户模拟时更接近用户的实际使用. 在进行压力测试时,经常会 ...