java编写网站数据抓取
来公司已经俩月了,每天加班平均工时11个小时的我又想起了老东家温馨舒适安逸的生活。已经有好久没时间读博客写博客了,我觉得我退步了,嗯嗯,我很不开心
今天记录下抓数据的一些东西吧。
数据抓取现在是很普遍的事情,有用Python的,当然我还是很弱,我只能用java搞,以下就是正经话了。
以下需要注意的:
1.首先有个目标,抓取的目标页面
2.目标页面的数据结构
3.目标网站是否有反爬虫机制(就是会封你ip)
4.数据解析之 存库
获取httpClient
package com.app.utils; import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException; @Component
public class HttpConnectionManager {
PoolingHttpClientConnectionManager cm = null; @PostConstruct
public void init() {
LayeredConnectionSocketFactory sslsf = null;
try {
sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
cm =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
} public CloseableHttpClient getHttpClient() {
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
return httpClient;
}
}
抓取页面工具类 因为很多网站都做了反爬虫机制,它会在单位时间内限制你的访问次数,如果你爬去的数据不停在变化,即时性要求很高,这就需要使用代理IP
package com.zyt.creenshot.util; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map; /**
* @ClassName:DocumentHelper
* @Description:<抓取页面工具类>
* @Author:zhaiyutao
* @Data:2019/7/1 11:15
* @Vesion: v1.0
*/
@Component
public class DocumentHelper { @Autowired
HttpConnectionManager connManager; public String getProxyHttp(String url, String address, int port, String charset) {
CloseableHttpResponse response = null;
CloseableHttpClient httpClient = connManager.getHttpClient();
try {
//发送get请求
HttpGet httpGet = new HttpGet(url);
//构建代理IP请求
httpGet = buildProxy(httpGet, address, port);
Map<String, String> headerMap = new HashMap<String, String>();
headerMap.put("Referer", "http://*********.com/");
headerMap.put("Content-Type", "text/html; charset=utf-8");
headerMap.put("User-Agent", UserAgentUtil.getRandomUserAgent());
headerMap.put("Accept-Language", "zh-CN,zh;q=0.9");
headerMap.put("Accept-Encoding", "gzip, deflate");
//构建请求header头
httpGet = buildRequestHeader(headerMap, httpGet);
response = httpClient.execute(httpGet);
response.addHeader("Content-Type", "text/html; charset=utf-8");
//获取响应实体
HttpEntity entity = response.getEntity();
if (entity != null) {
String content = EntityUtils.toString(entity);
if(null != charset && !"".equals(charset)) {
content = new String(content.getBytes(StandardCharsets.ISO_8859_1), charset);
}
return content;
}
} catch (Exception e){
//出现问题不处理异常 再次请求 最后统一处理
//log.error("代理解析内部出现问题 url {} address {} port {}",url,address,port);
return "";
}finally {
try {
response.close();
} catch (Exception e) {
}
}
return "";
} private static HttpGet buildProxy(HttpGet httpGet,String address,int port) {
RequestConfig requestConfig = null;
if(StringUtils.isNotEmpty(address)){
HttpHost proxy = new HttpHost(address, port);
requestConfig = RequestConfig.custom()
.setProxy(proxy)
.setConnectTimeout(4000)
.setSocketTimeout(8000)
.setConnectionRequestTimeout(4000)
.build();
}else{
requestConfig = RequestConfig.custom()
.setConnectTimeout(4000)
.setSocketTimeout(8000)
.setConnectionRequestTimeout(4000)
.build();
}
httpGet.setConfig(requestConfig);
return httpGet;
} /**
* 构建header头
* @param headerMap
* @param httpGet
* @return
*/
private static HttpGet buildRequestHeader(Map<String,String> headerMap,HttpGet httpGet) {
if (MapUtils.isNotEmpty(headerMap)) {
for (Map.Entry<String,String> kv :headerMap.entrySet()) {
httpGet.setHeader(kv.getKey(),kv.getValue());
}
}
return httpGet;
} }
请求头伪装工具类
package com.zyt.creenshot.util; import java.util.Random; public class UserAgentUtil { private static final String[] USER_AGENT = {
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", //google
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.109", //opera
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE", //
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Maxthon/5.2.7.3000", //遨游
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0", //firefox
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50" //safari
//"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763" //IE
}; /**
* 随机获取user-agent
* @return
*/
public static String getRandomUserAgent() {
Random random = new Random();
int i = random.nextInt(USER_AGENT.length);
String userAgent = USER_AGENT[i];
return userAgent;
} }
如下以爬取某个汽车网站数据为例 当然表的创建需要自己根据需要设计 我就不贴具体表结构了
package com.zyt.creenshot.service.crawlerData.impl; import com.zyt.creenshot.entity.CarBaseData;
import com.zyt.creenshot.mapper.CarBaseDataMapper;
import com.zyt.creenshot.service.crawlerData.ICrawlerData;
import com.zyt.creenshot.util.DocumentHelper;
import com.zyt.creenshot.util.HttpConnectionManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.ArrayList;
import java.util.List; /**
* @ClassName:CrawlerDataImpl
* @Description:<TODO>
* @Author:zhaiyutao
* @Data:2019/7/8 17:48
* @Vesion: v1.0
*/
@Component
@Slf4j
public class CrawlerDataImpl implements ICrawlerData { @Autowired
private HttpConnectionManager connectionManager; @Autowired(required = false)
private CarBaseDataMapper carBaseDataMapper; @Override
public void crawlerCarBaseData() { String url = "***********要爬取的网址*************";
String resultHtml = DocumentHelper.getProxyHttp(url, null, 0, "GBK", connectionManager);
if(StringUtils.isEmpty(resultHtml)){
log.error("没有爬到网站数据");
}
Document html = Jsoup.parse(resultHtml);
//解析品牌
Elements brandList = html.select("div[class=braRow]");
if(null != brandList && brandList.size() > 0 ){
List<CarBaseData> listCar = new ArrayList<>();
// 获取车的大品牌
for(Element brand : brandList){
Elements brandBig = brand.select("div[class=braRow-icon]");
//大品牌名称 和 车标
String brandName = brandBig.select("p").text().replace("?","·");
String brandPic = brandBig.select("img[src]").attr("#src"); Elements smallBrandList = brand.select("div[class=modA noBorder]");
for( Element sb : smallBrandList){
Elements brandItem = sb.select("div[class=thA]");
// 细分品牌
String brandSmallName = brandItem.select("a[href]").text(); Elements sbInner = sb.select("div[class=tbA ]");
for(Element in : sbInner){
dealCarData(listCar, brandName, brandPic, brandSmallName, in);
}
Elements sbInnerNother = sb.select("div[class=tbA mt10 noBorder]");
for(Element inner : sbInnerNother){
dealCarData(listCar, brandName, brandPic, brandSmallName, inner);
}
}
}
if(CollectionUtils.isNotEmpty(listCar)){
carBaseDataMapper.insertBatch(listCar);
}
}
} private void dealCarData(List<CarBaseData> listCar, String brandName, String brandPic, String brandSmallName, Element in) {
String carTypeName = in.select("p[class=stit]").text().split("(")[0];
Elements li = in.select("li");
for(Element element : li){
Element tit = element.select("p[class=tit]").get(0);
Element price = element.select("p[class=price]").get(0);
Elements carHref = tit.select("a[href]");
String priceStr = price.text();
if(null != carHref){
String href = carHref.attr("href");
if(StringUtils.isEmpty(href)){
continue;
}
String carName = carHref.attr("title");
String carId = StringUtils.substring(href, 1, href.length() - 1);
CarBaseData carBaseData = new CarBaseData();
carBaseData.setCarId(carId);
carBaseData.setCarName(carName);
carBaseData.setBrandName(brandName);
carBaseData.setBrandPic(brandPic);
carBaseData.setSubBrandName(brandSmallName);
carBaseData.setCarType(carTypeName);
carBaseData.setCarPrice(priceStr);
listCar.add(carBaseData);
}
if(listCar.size()>=500){
carBaseDataMapper.insertBatch(listCar);
listCar.clear();
}
}
}
}
爬取的数据:
java编写网站数据抓取的更多相关文章
- .net网站数据抓取
最新项目需要抓取人民币汇率中间价的数据,所以就写了个简单的爬虫抓取数据.抓取的网站为:http://www.safe.gov.cn/wps/portal/sy/tjsj_hlzjj_inquire # ...
- 倔强的网站数据抓取,关键时刻还需Webbrowser显身手
由于最近台风挺多,公司网站上需要挂上台风预报信息,就整了个抓取台风数据(至于抓数据的概念和实践手册我以前写的一篇博客里面有介绍:分享一套抓数据小程序,客户资料.实时新闻.股票数据…随心抓)的服务,做调 ...
- WebScraper for Mac(网站数据抓取软件) 4.10.2
WebScraper Mac版是一款Mac平台上通过使用将数据导出为JSON或CSV的简约应用程序,WebScraper Mac版可以快速提取与某个网页(包括文本内容)相关的信息.WebScraper ...
- 吴裕雄--天生自然python学习笔记:WEB数据抓取与分析
Web 数据抓取技术具有非常巨大的应用需求及价值, 用 Python 在网页上收集数据,不仅抓取数据的操作简单, 而且其数据分析功能也十分强大. 通过 Python 的时lib 组件中的 urlpar ...
- Java实现多种方式的http数据抓取
前言: 时下互联网第一波的浪潮已消逝,随着而来的基于万千数据的物联网时代,因而数据成为企业的重要战略资源之一.基于数据抓取技术,本文介绍了java相关抓取工具,并附上demo源码供感兴趣的朋友测试! ...
- C# 从需要登录的网站上抓取数据
[转] C# 从需要登录的网站上抓取数据 背景:昨天一个学金融的同学让我帮她从一个网站上抓取数据,然后导出到excel,粗略看了下有1000+条记录,人工统计的话确实不可能.虽说不会,但作为一个学计算 ...
- 【Python入门只需20分钟】从安装到数据抓取、存储原来这么简单
基于大众对Python的大肆吹捧和赞赏,作为一名Java从业人员,我本着批判与好奇的心态买了本python方面的书<毫无障碍学Python>.仅仅看了书前面一小部分的我......决定做一 ...
- 数据抓取的艺术(一):Selenium+Phantomjs数据抓取环境配置
数据抓取的艺术(一):Selenium+Phantomjs数据抓取环境配置 2013-05-15 15:08:14 分类: Python/Ruby 数据抓取是一门艺术,和其他软件不同,世界上 ...
- [原创.数据可视化系列之十二]使用 nodejs通过async await建立同步数据抓取
做数据分析和可视化工作,最重要的一点就是数据抓取工作,之前使用Java和python都做过简单的数据抓取,感觉用的很不顺手. 后来用nodejs发现非常不错,通过js就可以进行数据抓取工作,类似jqu ...
随机推荐
- luogu题解P1967货车运输--树链剖分
题目链接 https://www.luogu.org/problemnew/show/P1967 分析 NOIp的一道裸题,直接在最大生成树上剖分取最小值一下就完事了,非常好写,常数也比较小,然而题解 ...
- MySql8.0 安装重要的两步。
1.去官网下载mysql社区版 windows安装包. 2.在安装包 安装的过程中,有一步就是启动mysql 会失败: 然后修改服务后,再次回到安装界面点击:execute,就会成功了. 先去配置一下 ...
- VBA术语(三)
在本章中,将介绍常用的Excel VBA术语.这些术语将在很多的模块中使用,因此理解其中的每一个术语都很重要. 模块 模块是编写代码的区域.如下图中,这是一个新的工作簿,因此没有任何模块. 要插入模块 ...
- CVE-2019-0214: Apache Archiva arbitrary file write and delete on the server
CVE-2019-0214: Apache Archiva arbitrary file write and delete on the server Severity: Medium Vendor: ...
- CSS3弹性盒子(Flex Box)
CSS3弹性盒子(Flex Box) 一.容器的属性:flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-content 1 ...
- OpenCV 图象腐蚀形态学操作 全家桶
图象腐蚀与形态学操作 opencv 1. 通过调用库函数实现图像的腐蚀.膨胀: 2. 通过设置结构元素.元素大小.形态学操作类型实现对图象的形态学操作. 源码(VS2017+OpenCV 4.0) # ...
- 解决spring-boot-maven-plugin插件打包,springboot启动时报找不到主main问题
一:遇到的问题及解决方法 最近在搭建一个新项目时,使用spring-boot-maven-plugin插件打包,springboot项目在发布后启动时遇到找不到主main问题. 遇到这个问题当时感觉本 ...
- 使用url_for()时,会自动调用转换器的to_url()方法
视图反推url,在动态url(转换器)反推中的应用 # -*- coding: utf-8 -*- from flask import Flask, url_for, redirect from we ...
- Mysql中的锁机制-转载
原文:http://blog.csdn.net/soonfly/article/details/70238902 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的 计算资源(如 ...
- CLR ATL
前段时间,帮人改了个项目,里面明明感觉是MFC,但是却调用C#的类函数,用的都是gcnew指针,凭借着对C#的熟悉,一点一点的实验,终于帮人把程序改好了,但是却不知道到底是什么东西,C#和MFC的混合 ...