如何在爬数据需求数据采集系统中脱颖而出
优采云 发布时间: 2021-04-25 05:12如何在爬数据需求数据采集系统中脱颖而出
记录两年前编写的采集系统,包括需求,分析,设计,实现,遇到的问题和系统的有效性。系统的主要功能是为每个网站设置不同的网站。k15]规则配置为每个网站抓取数据。我两年前离开时,抓取的数据量约为数千万个级别。 采集的数据增量约为每天10,000。将[k15 网站]配置为1200以上,现在记录系统实施情况,并为每个人提供一些简单的爬网程序演示以学习如何对数据进行爬网
要求
数据采集系统:通过配置规则采集可以不同的系统网站
主要目标:
针对不同的网站,可以通过配置不同的采集规则来实现网页数据抓取。对于每条内容,可以定期提取特征数据以爬网所有网站数据。 采集配置规则可以是维护采集仓库数据的可维护性分析
当然,第一步是首先分析需求,因此我们正在提取系统的主要需求:
可以通过针对不同网站的不同采集规则来实现数据爬网。可以为每个内容提取特征数据。功能数据是指标题,作者和发布时间信息计时任务关联任务或任务组,以抓取网站的数据
再次分析网站的结构,只有两个;
一个是列表页面。此处的列表页面代表需要在当前页面上获取更多详细信息页面的Web链接的类型,就像常规查询列表一样,您可以通过列表获取更多详细信息页面链接。一个是详细信息页面。这种页面更容易理解。这种页面无需获得指向该页面上其他网页的链接,并且可以直接在当前页面上提取数据。
基本上所有网站抓取的内容都可以像这样抽象。
设计
基于分析结果的设计和实现:
任务表
每个网站都可以视为执行采集的任务
两个规则表
每个网站对应于其自己的采集规则。根据上面分析的网站结构,可以将采集规则进一步细分为两个表,一个收录网站链接以获取详细信息列表页面采集 Rule表的列表,规则表details 采集 网站详细信息页特征数据采集的规则表
网址表
负责记录采集目标网站详细信息页面的网址
计划任务的时间表
根据定时任务定期执行某些任务(可以使用定时任务与多个任务关联,或者可以考虑添加任务组表,定时任务与任务组以及任务组相关联与任务相关联)
数据存储表
这是因为我们的采集数据主要是用于投标和中标的两种数据。构建了两个数据存储表,分别是中标信息表和中标信息表
实施框架
基本结构是:ssm + redis + htmlunit + jsoup + es + mq + quartz
有许多框架可以在Java中实现采集器。有许多出色的开源框架,例如htmlunit,WebMagic,jsoup等。当然,httpclient也可以实现。
为什么使用htmlunit?
htmlunit是一个开放源代码Java页面分析工具。阅读页面后,您可以有效地使用htmlunit分析页面上的内容。该项目可以模拟浏览器操作,被称为Java浏览器的开源实现
简单说说我对htmlunit的理解:
一个是htmlunit提供了通过xpath定位页面元素的功能,可用于提取页面特征数据;第二个是对js的支持,对js的支持意味着您可以将它真正视为浏览器,可以使用它来模拟点击,输入,登录和其他操作,对于采集,支持js可以解决使用问题ajax获取页面上的数据。当然,除此之外,htmlunit还支持代理ip,https,通过配置,您可以模拟浏览器,例如Google,Firefox,Referer,用户代理,是否加载js,css,是否支持ajax等。
XPath语法是XML路径语言(XML Path Language),它是一种用于确定XML文档某一部分位置的语言。
为什么要使用jsoup?
与htmlunit相比,jsoup提供了类似于jquery选择器的定位页面元素的功能,两者可以互补使用。
采集
采集数据逻辑分为两部分:url 采集器,详细信息页面采集器
url 采集器:
详细信息页面采集器:
重复数据删除遇到问题:采集 url重复数据删除后,url重复数据删除。通过将密钥作为URL存储在redis中,缓存时间为3天。此方法是为了防止重复相同的A url 采集。重复数据删除由标题执行。通过将标题采集用密钥存储在redis中,缓存时间为3天。这种方法是为了防止文章文章由不同的网站发表,并重复出现采集的情况。数据质量:
因为每个网站页面都不相同,尤其是同一网站的详细页面结构不同,这增加了特征数据提取的难度,因此使用htmlunit + jsoup +结合使用三种常规方法来删除采集特征数据。
采集效率:
由于采集中有许多网站,假设每个任务执行打开一个列表页面和十个详细信息页面,那么一千个任务的执行需要采集 11000个页面,因此请使用url与详细信息页面采集分开,通过mq实现异步操作,并通过多线程实现url和详细信息页面的采集。
封锁的IP:
对于网站,假设它每半小时执行一次,则网站每天将被扫描48次,并且还假设一次采集将打开11页,即528次一天,所以这是密封是一个非常普遍的问题。解决方案是htmlunit提供代理ip的实现。使用代理ip可以解决ip阻塞的问题。代理ip的来源:一种是Internet上有很多代理ip 网站。您可以直接购买他们的代理IP。 ,另一个是进行爬网,这些网站销售代理ip都提供了一些免费的代理ip,您可以将这些ip爬回,然后使用httpclient或其他方法来验证代理ip的可用性,如果可以输入数据库的话直接建立自己的代理IP库。由于代理ip对时间敏感,因此您可以创建一个定时任务来刷刷ip库并删除无效的ip。
网站无效:
网站有两种无效类型。一种是域名为网站,并且原创URL无法直接打开。第二个是网站的修订版。所有原创配置的规则均无效,并且不能采集]来使数据有效。解决此问题的方法是每天发送采集数据并记录电子邮件提醒,并采集尚未采集的数据和尚未打开的网页,然后通过电子邮件将其发送给相关人员。
验证码:
当时,对于网站 采集历史数据采集,方法是通过其列表页面转到采集详细信息页面。 采集发现经过成千上万的数据后,网站我再也无法获取数据了。查看页面后,我发现验证码已添加到列表页面。该验证码是一个相对简单的数字加字母。当时,我想在列表页面添加验证码吗? ,然后想出一个解决方案,我找到了一个开源的orc文本识别项目tess4j(请参阅此处以了解如何使用它),过一会儿没关系,识别率约为20%,因为htmlunit可以在因此,代码中的操作是首先通过htmlunit的xpath获取验证码元素,获取验证码图片,然后使用tess4j标识验证码,然后将识别出的验证码填写到验证中代码输入框,单击翻页,如果验证码通过,则翻页进行后续操作采集,如果失败,请重复上述识别验证码操作,直到知道成功为止,将验证码输入输入框并单击以打开页面可以使用htmlunit
Ajax加载数据:
有些网站使用ajax加载数据。使用htmlunit 采集时,网站需要在获取HtmlPage对象后给页面一个时间来加载ajax,然后可以通过HtmlPage获取它。加载ajax之后的数据。
代码:webClient.waitForBackgroundJavaScript(time);您可以看到稍后提供的演示
系统的总体架构图,这里我们指的是data 采集系统的一部分
演示
采集器的实现:
@GetMapping("/getData")
public List article_(String url,String xpath){
WebClient webClient = WebClientUtils.getWebClientLoadJs();
List datas = new ArrayList();
try {
HtmlPage page = webClient.getPage(url);
if(page!=null){
List lists = page.getByXPath(xpath);
lists.stream().forEach(i->{
DomNode domNode = (DomNode)i;
datas.add(domNode.asText());
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
webClient.close();
}
return datas;
}
上面的代码实现采集列表页
爬博客园
请求以下网址:: 9001 / getData?url =; xpath = // * [@ id =“ post_list”] / div / div [2] / h3 / a
网页:
采集的数据返回:
再次爬csdn
再次请求:: 9001 / getData?url =; xpath = // * [@ id =“ feedlist_id”] / li / div / div [1] / h2 / a
网页:
采集的数据返回:
采集步骤
通过一个方法去采集两个网站,通过不同url和xpath规则去采集不同的网站,这个demo展示的就是htmlunit采集数据的过程。
每个采集任务都是执行相同的步骤
- 获取client -> 打开页面 -> 提取特征数据(或详情页链接) -> 关闭cline
不同的地方就在于提取特征数据
优化:使用模板方法设计模式提取功能部分
以上代码可以提取为:采集执行程序,自定义采集数据实现
/**
* @Description: 执行者 man
* @author: chenmingyu
* @date: 2018/6/24 17:29
*/
public class Crawler {
private Gatherer gatherer;
public Object execute(String url,Long time){
// 获取 webClient对象
WebClient webClient = WebClientUtils.getWebClientLoadJs();
try {
HtmlPage page = webClient.getPage(url);
if(null != time){
webClient.waitForBackgroundJavaScript(time);
}
return gatherer.crawl(page);
}catch (Exception e){
e.printStackTrace();
}finally {
webClient.close();
}
return null;
}
public Crawler(Gatherer gatherer) {
this.gatherer = gatherer;
}
}
将接口插入Crawler,此接口只有一个方法crawl(),不同的实现类将实现此接口,然后自定义特征数据的实现
/**
* @Description: 自定义实现
* @author: chenmingyu
* @date: 2018/6/24 17:36
*/
public interface Gatherer {
Object crawl(HtmlPage page) throws Exception;
}
优化代码:
@GetMapping("/getData")
public List article_(String url,String xpath){
Gatherer gatherer = (page)->{
List datas = new ArrayList();
List lists = page.getByXPath(xpath);
lists.stream().forEach(i->{
DomNode domNode = (DomNode)i;
datas.add(domNode.asText());
});
return datas;
};
Crawler crawler = new Crawler(gatherer);
List datas = (List)crawler.execute(url,null);
return datas;
}
不同的实现,只需要修改接口实现的这一部分。
数据
最后使用采集系统采集查看数据。
效果
效果还是不错的,最重要的是系统稳定运行:
采集的历史数据约为6-7百万。 采集的新数据增量约为每天10,000。该系统目前装有1200多个任务(定时执行将转到采集这些网站)数据
系统配置采集的网站主要用于国家网站的省,市,县的招标信息(当前配置了1,200多个采集站点)。
采集的数据主要用作公司的数据中心,为一个PC终端网站和2个微信公众号提供数据
欢迎关注并掌握第一手竞标信息
以PC端显示的采集的中标数据为例,看看采集的效果:
本文只是从零到整个过程的采集系统的粗略记录,当然,它也遇到了本文中未提及的许多问题。