注解模式抓取table中每行tr情况
package com.lsiding.robot.page.model;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.model.AfterExtractor;
import us.codecraft.webmagic.model.ConsolePageModelPipeline;
import us.codecraft.webmagic.model.OOSpider;
import us.codecraft.webmagic.model.PageModelExtractorProxy;
import us.codecraft.webmagic.model.annotation.ExtractBy;
import us.codecraft.webmagic.model.annotation.ExtractBy.Type;
/**
* 建造师列表页面(基础信息)
*
* @author liyixing
*
*/
//@TargetUrl("http://59.52.254.106:8093/outQualificationQuery\\S+")
@ExtractBy(value = "//div[@class='addProject']/table//tr", multi = true)
public class BuilderBaseModel implements AfterExtractor {
/**
* 是否已经获取所有的分页列表所有页面
*/
public static boolean isAddTargetRequests = false;
/**
* 重新开始获取所有的分页列表所有页面 liyixing
*/
public static void doIsAddTargetRequests() {
isAddTargetRequests = false;
}
/**
* 获取所有的分页列表所有页面结束 liyixing
*/
public static void endIsAddTargetRequests() {
isAddTargetRequests = true;
}
/**
* 姓名
*/
@ExtractBy(value = "//tr//td[2]//a/allText()", notNull = true, type = Type.XPath)
private String name;
/**
* 详情链接
*/
@ExtractBy(value = "//tr//td[2]/a/@onclick", notNull = true, type = Type.XPath)
private String detail;
/**
* 所属公司
*/
@ExtractBy(value = "//tr//td[3]/allText()", notNull = true, type = Type.XPath)
private String company;
/**
* 注册编号
*/
@ExtractBy(value = "//tr//td[4]/allText()", notNull = true, type = Type.XPath)
private String registerNumber;
/**
* 证书编号
*/
@ExtractBy(value = "//tr//td[5]/allText()", notNull = true, type = Type.XPath)
private String cerNumber;
/**
* 資格證書编号
*/
@ExtractBy(value = "//tr//td[6]/allText()", notNull = true, type = Type.XPath)
private String qualCerNumber;
/**
* 状态
*/
@ExtractBy(value = "//tr//td[7]/allText()", notNull = true, type = Type.XPath)
private String status;
/**
* 注册专业
*/
@ExtractBy(value = "//tr//td[8]/allText()", notNull = false, type = Type.XPath)
private String major;
/**
* 注册有效期
*/
@ExtractBy(value = "//tr//td[9]/allText()", notNull = false, type = Type.XPath)
private String valTime;
/**
* 姓名
*/
public String getName() {
return name;
}
/**
* 姓名
*/
public void setName(String name) {
this.name = name;
}
/**
* 解析完毕
*/
@Override
public void afterProcess(Page page) {
//处理详情地址
detail = "http://59.52.254.106:8093/"+detail.replace("winopen('", "")
.replace("',1000,600,'人员证书轨迹查看');", "");
//根据总记录数计算总页面数
if (!isAddTargetRequests && StringUtils.isNotBlank(name)) {
// 根据分页数,增加爬取链接
Integer allNumber = Integer
.valueOf(page
.getHtml()
.xpath("//div[@class='paging']//span[@class='localPage'][2]/tidyText()")
.get());
//
List<String> urls = new ArrayList<String>();
// 计算总共有多少页
int pageMaxSize = allNumber / 50;
if (allNumber % 50 != 0) {
pageMaxSize++;
}
for (int x = 2; x <= pageMaxSize; x++) {
urls.add("http://59.52.254.106:8093/outQualificationQuery?pageSize=50&pageIndex="
+ x + "&q_certStatus=0");
}
page.addTargetRequests(urls);
endIsAddTargetRequests();
}
}
public static void main(String[] args) throws IllegalAccessException {
BuilderBaseModel.doIsAddTargetRequests();
Spider ooSpider = OOSpider.create(
Site.me()
.setRetryTimes(3)
.setSleepTime(100)
.setUserAgent(
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"),
new ConsolePageModelPipeline(), BuilderBaseModel.class)
// 从"某个地址再试抓取"开始抓
.addUrl("http://59.52.254.106:8093/outQualificationQuery?pageSize=50&pageIndex=1&q_certStatus=0")
// 开启5个线程抓取
.thread(5);
// 启动爬虫
PageModelExtractorProxy.updatePageModelExtractor(ooSpider);
ooSpider.run();
}
}
如上,tr在jsoup中,纯粹的tr开头的html在jsoup解析中,tr和td将会被删除,需要再
public Object process(Page page) {
boolean matched = false;
for (Pattern targetPattern : targetUrlPatterns) {
if (targetPattern.matcher(page.getUrl().toString()).matches()) {
matched = true;
}
}
if (!matched) {
return null;
}
try {
Method method = PageModelExtractor.class.getDeclaredMethod(
"processSingle", Page.class, String.class, boolean.class);
method.setAccessible(true);
if (objectExtractor == null) {
return method.invoke(pageModelExtractor, page, null, true);
} else {
if (objectExtractor.multi) {
List<Object> os = new ArrayList<Object>();
List<String> list = objectExtractor.getSelector()
.selectList(page.getRawText());
for (String s : list) {
Object o;
// 给s追加table
if (s.startsWith("<tr>")) {
s = "<table>" + s + "</table>";
}
o = method.invoke(pageModelExtractor, page, s, false);
if (o != null) {
os.add(o);
}
}
return os;
} else {
String select = objectExtractor.getSelector().select(
page.getRawText());
Object o;
o = method.invoke(pageModelExtractor, page, select, false);
return o;
}
}
} catch (Exception e1) {
throw new RuntimeException(e1);
}
}
// 给s追加table
if (s.startsWith("<tr>")) {
s = "<table>" + s + "</table>";
}
xpath的[index]模式
该模式会对table失效,比如//table[1]
因此如果table前面有div可以采用
//div[@xx='xxxxx'][x]//table的模式
分享到:
相关推荐
php : failed to load external entity namedmanager.wsdl ; nslookup, dig : time out ; dns 服务器本机测试不通,其他机器测试不通的解决办法
在Android开发中,有时我们需要实现同时在两个GLSurfaceView上显示摄像头预览的效果,例如在进行视频通话或者多画面监控的应用场景。然而,这并非易事,因为涉及到多个GLSurfaceView与摄像头预览数据的同步处理,...
这个时候先别急着找后端,只要能下载生成想要的文件,文件打开内容是正确的都好说.下面总结几种生成导出的写法: 一. a标签点击下载 let blob = new Blob([res.data], {type: 'application/vnd.ms-excel'}); let link =...
绿色闭坑是一个涉及矿区环境恢复与可持续发展的概念,它不仅仅关注矿产资源的开采,更着重于矿产后期的治理和生态环境的保护。本文结合徐州贾汪矿区闭坑前综合治理的实践,深入探讨了“绿色闭坑”的基本概念、主要...
综上所述,这篇文章或培训材料可能涵盖了以下几个关键知识点: 1. **Storm核心概念**:包括Spouts(数据源)、Bolts(处理逻辑)、Topology(任务拓扑结构)以及Stream Groupings(数据分发策略)等。 2. **故障...
在实施量化交易时,需要特别注意以下几个“坑”: 1. **市场复杂性**:市场并非总是可预测的,价格波动受多种因素影响,简单的算法可能无法应对复杂环境。 2. **过度拟合**:在模型开发中,过度依赖历史数据可能...
二、全局的组件的坑 由于我的g-icon是全局注册的,所以使用g-input组件时的时候g-icon是直接用的,所以测试时有关icon的代码永远是错的。 把g-icon局部注册的组件 三、在测试中触发点击事件 模拟我在app.vue里使用...
Android studio+SQLCipher加密SQLite数据库的几个坑-附件资源
以下是关于这个指标的详细解读: 1. **RSI指标**: - RSI,即相对强弱指数(Relative Strength Index),是衡量证券价格涨跌速度的一种动量指标。 - 公式中,`RSI:=SMA(MAX(C-A,0),6,1)/SMA(ABS(C-A),6,1)*100`,...
【黄金坑—预警 预涨停的黄金坑预警源码】是通达信软件中一个专门用于条件选股的公式,其目标是提前发现可能即将涨停的股票,为投资者提供预警信号。该公式由多个技术指标组合而成,通过复杂的数学计算来判断股票的...
以下是一些关于`typeof`运算符需要注意的关键点: 1. **`null`的特殊情况**: `typeof`对`null`的判断结果是`'object'`,这可能与实际的预期不符,因为`null`实际上并不是一个对象。尽管如此,你不能将`null`当作...
根据给定文件的信息来看,这份文档似乎与IT行业并不直接相关,而是关于学前教育领域中大班阅读区活动的研究。不过,基于题目要求,我们可以从中提取并转换为与IT相关的知识点,比如通过类比的方式,将幼儿园大班阅读...
CDN 节点缓存策略包括两级节点架构 L1 和 L2 节点,L1 节点分布在全国各省市,L2 节点分布在几个大区下。 CDN 的优点: 使用 CDN 可以减少用户侧的延时,提高网站访问速度,降低服务器负载,提高网站的稳定性和...
在使用增强for循环时,需要注意以下几点: * 增强for循环只能用于遍历集合或数组,不可以用于遍历普通对象。 * 在遍历过程中,不能修改集合或数组的内容,以免引发ConcurrentModificationException异常。 * 使用...
【高考物理的34个坑】是针对高中物理学习中常见的难点和易错点的总结。以下是其中几个关键知识点的详细解析: 1. **受力分析**:在高中物理中,对物体进行受力分析至关重要,它涉及到重力、弹力、摩擦力等多个力的...
本系统的构成主要包括以下几个模块:电源模块、水位采集模块、数据处理模块、传输模块、上位机的实时监控模块以及预警模块。电源模块负责将电梯井道中的220V交流电转换为5V直流电,以保证单片机及其他模块的正常运行...
在深入探讨具体的重构技巧之前,我们先来了解几个重构的基本原则: 1. **确保测试覆盖**:重构前确保有完整的单元测试覆盖是非常重要的。这样可以保证在重构过程中及时发现引入的新bug。 2. **小步快走**:每次只...
株洲发电厂垃圾坑基础底板大体积混凝土施工方案是一份详细指导垃圾坑建设的技术文档,主要涉及以下几个核心知识点: 1. **工程概况**: - 垃圾坑的尺寸为61m长,23.7m宽,深度从±0.000m到-7.00m至-7.3m。 - 底板...