java从网页抓取数据(有type,记录如下流程状态->入库(组图))
优采云 发布时间: 2021-11-10 18:04java从网页抓取数据(有type,记录如下流程状态->入库(组图))
背景说明
由于目标页面是用vue结构写的,所以无法使用urlConnection获取连接然后使用Document/Jsoup解析。页面元素通过js动态渲染。后来尝试使用webMagic框架配合selenium\Chrome来抓取和组织基础数据。
过程
设计一个标记表结构,记录捕获的状态、数据等。配置selenium相关环境和工具,分析页面的dom元素。html进程的编码解析过程会在webmagic框架的处理器层和流水线层进行编码集成和调试。对获取的数据存储操作有效
台阶分析
1. 标注的表结构设计和示例表如下
CREATE TABLE `data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT 'dataname',
`type` tinyint(4) DEFAULT NULL COMMENT '类型',
`xx` int(11) DEFAULT '0' COMMENT '修订',
`xx` ...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='数据标记'
制作这张表的初衷是对抓取到的数据做一个基本的保留,提取过程中的核心数据作为后期的统计和验证处理。因为不相信爬取数据的结果【可能是网络中断,页面无法正常打开,页面打开后页面布局混乱,并发条件下浏览器窗口意外关闭,页面添加和更改修订元素等。获取目标数据]。所以有一个type字段,记录如下进程状态
爬取->打开->操作->分析->入库->爬取
其中
1.爬取 是指抓取根路径或者获取到页面上的目标url路径;
2.打开 是指通过Chrome driver打开url的过程;
3.操作 是指需要通过selenium模拟点击、跳转、输入等操作;
4.解析 是指到达目标页面后对html元素进行解析并获取有效内容
5.入库 将内容进行持久化操作
6.爬取 获取下一级链接,循环此操作
这里最不可控的一步是2、3、4。由于各种原因,可能会出现各种问题。所以需要记录当前数据的执行状态。当然,如果数据是可丢失的、可重复的、对你来说值得信赖的,你完全可以忽略部分数据,以量取胜。
2. Selenium 相关环境配置
首先引入jar,下载浏览器对应的驱动并配置
org.seleniumhq.selenium
selenium-java
3.9.1
org.seleniumhq.selenium
selenium-server
3.9.1
org.yaml
snakeyaml
上面是pom配置,下面是驱动变量设置,
static
{
System.getProperties().setProperty("webdriver.chrome.driver", "/Users/chenhailong/Downloads/tools/nessarytool/chromedriver");
}
运行以下代码时,可以正常打开浏览器,说明配置正常
WebDriver w = new ChromeDriver();
w.get("https://www.deathearth.com");
# 控制台会输出以下信息
Starting ChromeDriver 2.38.552518 (183d19265345f54ce39cbb94cf81ba5f15905011) on port 33558
Only local connections are allowed.
八月 23, 2019 5:02:46 下午 org.openqa.selenium.remote.ProtocolHandshake createSession
信息: Detected dialect: OSS
这种环境下最容易出现的问题是浏览器版本和驱动版本不一致,导致程序无法打开浏览器。或者是浏览器自动升级的影响。只需仔细配置即可。
3. 解析页面上的html元素
一种。这里最麻烦的就是页面修改问题,刚刚写了一套匹配规则来处理。但是目标网站经常改变布局,调整按钮功能的效果。因此,它基本上需要随着目标网站的变化而变化。没门。
湾 其次,还有分析效率的问题。我遇到过两种情况。一种是在抓取长文本(超过10w字节)文章的内容时,通过父元素的text()方法读取,内容被截断。导致信息不全。这是通过循环子标签处理的。如下
<p>
...
...
修改前: w.findElements(By.id("content")).getText()
修改后:List ls = w.findElements(By.xpath("div"))
for(int i = 0;i