转载请注明:http://mp.blog.csdn.net/postedit/79131443
首先编写HtmlUtils类,这个类将一些常用方法集成到一个类里面。
工具类
public class HtmlUtil {
/*
* 启动JS
*/
public static WebClient iniParam_Js() {
final WebClient webClient = new WebClient(BrowserVersion.CHROME);
// 启动JS
webClient.getOptions().setJavaScriptEnabled(true);
//将ajax解析设为可用
webClient.getOptions().setActiveXNative(true);
//设置Ajax的解析器
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
// 禁止CSS
webClient.getOptions().setCssEnabled(false);
// 启动客户端重定向
webClient.getOptions().setRedirectEnabled(true);
// JS遇到问题时,不抛出异常
webClient.getOptions().setThrowExceptionOnScriptError(false);
// 设置超时
webClient.getOptions().setTimeout(10000);
//禁止下载照片
webClient.getOptions().setDownloadImages(false);
return webClient;
}
/*
* 禁止JS
*/
public static WebClient iniParam_NoJs() {
final WebClient webClient = new WebClient(BrowserVersion.CHROME);
// 禁止JS
webClient.getOptions().setJavaScriptEnabled(false);
// 禁止CSS
webClient.getOptions().setCssEnabled(false);
// 将返回错误状态码错误设置为false
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
// 启动客户端重定向
webClient.getOptions().setRedirectEnabled(true);
// 设置超时
webClient.getOptions().setTimeout(5000);
//禁止下载照片
webClient.getOptions().setDownloadImages(false);
return webClient;
}
/**
* 根据url获取页面,这里需要加载JS
* @param url
* @return 网页
* @throws FailingHttpStatusCodeException
* @throws MalformedURLException
* @throws IOException
*/
public static HtmlPage getPage_Js(String url) throws FailingHttpStatusCodeException, MalformedURLException, IOException{
final WebClient webClient = iniParam_Js();
HtmlPage page = webClient.getPage(url);
//webClient.waitForBackgroundJavaScriptStartingBefore(5000);
return page;
}
/**
* 根据url获取页面,这里不加载JS
* @param url
* @return 网页
* @throws FailingHttpStatusCodeException
* @throws MalformedURLException
* @throws IOException
*/
public static HtmlPage getPage_NoJs(String url) throws FailingHttpStatusCodeException, MalformedURLException, IOException{
final WebClient webClient = iniParam_NoJs();
HtmlPage page = webClient.getPage(url);
return page;
}
}
这样做的原因是使用HtmlUnit时经常需要设置JS,CSS等,这些代码都是大量重复的,为了减少代码量,我将这些方法写到一起。
根据姓名和机构获取匹配的学者的所有论文信息
public class GetArticles_CNC {
public static void main(String[] args) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
// 禁止日志的输出
LogManager.getLogManager().reset();
long time1 = System.currentTimeMillis();
System.out.println(getAllArticles("吴启夏", "华中理工大学"));
}
/**
* 以专家的姓名为关键词使用知网的学者搜索获取专家的所有论文的链接
*
* @param author 作者姓名
* @param expertOrg 作者机构
* @return 论文对应链接的list集合
* @throws FailingHttpStatusCodeException
* @throws MalformedURLException
* @throws IOException
*/
public static List<String> getAllArticles(String author, String expertOrg)
throws FailingHttpStatusCodeException, MalformedURLException, IOException {
// 获取客户端,禁止JS
WebClient webClient = HtmlUtil.iniParam_Js();
// 获取搜索页面
@SuppressWarnings("deprecation")
String url = "http://kns.cnki.net/kcms/detail/knetsearch.aspx?sfield=au&skey=" + URLEncoder.encode(author);
//获取搜索页面,搜索页面包含多个学者,机构通常是非完全匹配,姓名是完全匹配的,我们需要对所有的学者进行匹配操作
HtmlPage page = webClient.getPage(url);
//获取搜索页面的机构对应的节点
DomElement orgDom = page.getFirstByXPath("/html/body/div[7]/div[1]/div/p[1]");
if (orgDom == null)// 当机构节点为空时表示没有搜索到结果,直接返回空
return null;
//获取机构名称
String firstOrg = orgDom.asText();
// 判断学者机构和专家机构是否匹配
if (firstOrg.equals(expertOrg))
// 如果匹配则返回该学者的所有论文链接集合
return getArticlesOnCurAuthor(page);
else {// 否则需要获取其他同名作者的机构并判断是否匹配并判断
DomElement dupNameAuthorsDom = page.getFirstByXPath("/html/body/div[7]/div[2]/ul");//包含其他学者的节点
if (dupNameAuthorsDom == null)
return null;
//循序每一个学者的节点并判断是否匹配
for (DomElement authorDom : dupNameAuthorsDom.getChildElements()) {
String curOrg = authorDom.getFirstElementChild().getNextElementSibling().asText();
if (curOrg.equals(expertOrg)) {
String onclickAttr = authorDom.getFirstElementChild().getFirstElementChild()
.getAttribute("onclick");
String id = onclickAttr.substring(onclickAttr.indexOf(",") + 2, onclickAttr.lastIndexOf("'"));
String curUrl = url + "&code=" + id;
HtmlPage curPage = webClient.getPage(curUrl);
return getArticlesOnCurAuthor(curPage);
}
}
}
return null;
}
/**
* 获取某个学者页面中的所有的论文,这里的论文包含期刊论文,会议论文和硕博论文
*
* @param page
* @return
* @throws IOException
*/
public static List<String> getArticlesOnCurAuthor(HtmlPage page) throws IOException {
List<String> articlesList = new LinkedList<>();
WebClient webClient = page.getWebClient();
page.getElementById("lcatalog_1").click();// 发表在期刊上的文献
page.getElementById("lcatalog_3").click();// 发表在会议上的文献
page.getElementById("lcatalog_2").click();// 发表在博硕上的文献
webClient.waitForBackgroundJavaScriptStartingBefore(5000);// 设置等待时间为5s
HtmlPage jPage = (HtmlPage) webClient.getWebWindowByName("framecatalog_1").getEnclosedPage();
HtmlPage cPage = (HtmlPage) webClient.getWebWindowByName("framecatalog_3").getEnclosedPage();
HtmlPage sPage = (HtmlPage) webClient.getWebWindowByName("framecatalog_2").getEnclosedPage();
articlesList.addAll(getPageArticles(jPage, 1));
articlesList.addAll(getPageArticles(cPage, 2));
articlesList.addAll(getPageArticles(sPage, 3));
return articlesList;
}
/**
* 根据页面类型获取所有分页论文
*
* @param page 当前页面
* @param type 页面类型 1表示期刊论文页面,2表示会议论文页面,3表示硕博论文页面
* @return 所有论文列表的字符串形式
* @throws IOException
*/
public static List<String> getPageArticles(HtmlPage page, int type) throws IOException {
List<String> articlesList = new LinkedList<>();
// 获取不同类型页面分页数目
String id = "";// 页面中论文总数节点的id属性值
if (type == 1)
id = "pc_CJFQ";
else if (type == 2)
id = "pc_CPFD";
else if (type == 3)
id = "pc_CMFD";
DomElement aCountDom = page.getElementById(id);// 论文数量节点
// 如果论文数量节点为空则直接返回空字符串
if (aCountDom == null)
return articlesList;
HtmlPage tempPage = page;
articlesList.addAll(getArticlesByNode(tempPage));// 将当前页面中的所有论文添加到
while (true) {
DomElement nextDom = null;// 获取下一个及节点
try {
nextDom = tempPage.getAnchorByText("下一页");
} catch (ElementNotFoundException e) {
// TODO: handle exception
}
if (nextDom == null)
break;
tempPage = nextDom.click();// 获取下一页页面
page.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);// 设置等待时间为1S
articlesList.addAll(getArticlesByNode(tempPage));// 将当前页面中的所有论文添加到
}
return articlesList;
}
/**
* 根据节点获取单个页面的所有论文信息
*
* @param page
* 页面,这里的页面指包含论文的页面,期刊论文页面、会议论文页面和硕博论文页面
* @return
*/
public static List<String> getArticlesByNode(HtmlPage page) {
DomElement articlesNode = page.getFirstByXPath("/html/body/div[1]/div/div[2]/ul");
List<String> articlesList = new LinkedList<>();
for (DomElement li : articlesNode.getChildElements()) {
HtmlAnchor anchor = (HtmlAnchor) li.getFirstElementChild().getNextElementSibling();
String articleUrl = "http://kns.cnki.net" + anchor.getHrefAttribute();
String articleTitle = anchor.asText();
articlesList.add(articleTitle + ";" + articleUrl);
}
return articlesList;
}
/**
* 以姓名和机构为关键词,使用知网的高级搜索获取专家的所有论文
*
* @param author 专家姓名
* @param org 专家机构
* @return 论文list
* @throws IOException
*/
public static List<String> getArticlesByKeywords(String author, String org) throws IOException {
HtmlPage researchPage = HtmlUtil.getPage_Js("http://kns.cnki.net/kns/brief/result.aspx?dbprefix=SCDB");// 获取知网的高级搜索页面
HtmlTextInput authorInput = researchPage.getFirstByXPath("//*[@id=\"au_1_value1\"]");// 作者文本框
authorInput.setText(author);// 将作者填入
HtmlTextInput orgInput = researchPage.getFirstByXPath("//*[@id=\"au_1_value2\"]");// 机构文本框
orgInput.setText(org);// 将机构填入
HtmlButtonInput searchButton = researchPage.getFirstByXPath("//*[@id=\"btnSearch\"]");// 提交按钮
searchButton.click();// 获取提交后的页面
researchPage.getWebClient().waitForBackgroundJavaScriptStartingBefore(5000);// 等待5S
// 获取文章的iFrame页面
HtmlPage articlePage = (HtmlPage) researchPage.getWebClient().getWebWindowByName("iframeResult")
.getEnclosedPage();
// 获取第一篇文章节点
DomElement firstArticleDom = ((DomElement) articlePage
.getFirstByXPath("//*[@id=\"ctl00\"]/table/tbody/tr[2]/td/table/tbody")).getFirstElementChild()
.getNextElementSibling();
while (firstArticleDom != null) {
HtmlPage authorPage = getMatchedUrl(firstArticleDom, org);
if (authorPage != null)
return getArticlesOnCurAuthor(authorPage);
else {
firstArticleDom = firstArticleDom.getNextElementSibling();
}
}
return null;
}
/**
* 根据机构名获取匹配的学者主页
*
* @param articleDom 文章节点
* @param org 机构
* @return 如果学者主页的机构名和专家机构名匹配则返回匹配的学者主页,否则返回null
* @throws IOException
*/
public static HtmlPage getMatchedUrl(DomElement articleDom, String org) throws IOException {
DomElement authorDom = articleDom.getFirstElementChild().getNextElementSibling().getNextElementSibling();
for (DomElement curAuthorAnchor : authorDom.getChildElements()) {
if (curAuthorAnchor.getChildElementCount() != 0) {
HtmlPage curPage = curAuthorAnchor.click();
DomElement orgDom = curPage.getFirstByXPath("/html/body/div[7]/div[1]/div/p[1]/a");
if (orgDom.asText().contains(org))
return curPage;
}
}
return null;
}
}
最后程序的运行结果为:
[支持网络建模和仿真的Modelica模型管理框架;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSFZ201304018&dbcode=CJFQ&dbname=CJFD2013&v=, 基于交付物的汽车产品研发项目管理研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=XXGY201307000&dbcode=CJFQ&dbname=CJFD2013&v=, 协同环境中基于轻量化的3D异构CAD模型干涉检查;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX201301013&dbcode=CJFQ&dbname=CJFD2013&v=, 基于Fuzzy-PID的UUV姿态控制器研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JCGC201112023&dbcode=CJFQ&dbname=CJFD2011&v=, 基于参数树状约束的零部件族结构模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX201117010&dbcode=CJFQ&dbname=CJFD2011&v=, 集成项目管理与工作流的层次化过程模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX201114011&dbcode=CJFQ&dbname=CJFD2011&v=, 并发试验环境下的设备排程研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=SJSJ201104084&dbcode=CJFQ&dbname=CJFD2011&v=, 工作流的动态变更处理方法;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF201102017&dbcode=CJFQ&dbname=CJFD2011&v=, 大规模定制环境下的参数驱动产品配置设计方法研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX201015015&dbcode=CJFQ&dbname=CJFD2010&v=, 产品全生命周期数据信息的域建模方法;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF201002025&dbcode=CJFQ&dbname=CJFD2010&v=, 工作流的动态变更处理方法;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF201102017&dbcode=CJFQ&dbname=CJFD2011&v=, 大规模定制环境下的参数驱动产品配置设计方法研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX201015015&dbcode=CJFQ&dbname=CJFD2010&v=, 产品全生命周期数据信息的域建模方法;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF201002025&dbcode=CJFQ&dbname=CJFD2010&v=, 基于智能化配置的产品方案设计方法;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200919001&dbcode=CJFQ&dbname=CJFD2009&v=, 基于产品模型的多级产品配置研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=WJSJ200803008&dbcode=CJFQ&dbname=CJFD2008&v=, 面向飞机制造企业的计划管理系统的设计;http://kns.cnki.net/kcms/detail/detail.aspx?filename=WJSJ200736006&dbcode=CJFQ&dbname=CJFD2007&v=, 基于智能客户端的PLM系统体系框架;http://kns.cnki.net/kcms/detail/detail.aspx?filename=WJSJ200736013&dbcode=CJFQ&dbname=CJFD2007&v=, 可视化产品配置技术的研究与实现;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JCYY200705005&dbcode=CJFQ&dbname=cjfd2007&v=, 变量-知识体表达的产品开发过程模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200705014&dbcode=CJFQ&dbname=cjfd2007&v=, 基于五维状态空间的产品建模方法研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200704007&dbcode=CJFQ&dbname=cjfd2007&v=, 面向产品开发的项目管理在产品数据管理中的研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJJ200701019&dbcode=CJFQ&dbname=cjfd2007&v=, 网络化协同产品开发机理与模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200701009&dbcode=CJFQ&dbname=cjfd2007&v=, PLM系统中工作流访问控制模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX2006S2051&dbcode=CJFQ&dbname=cjfd2006&v=, 基于事物特性表的参数化产品配置;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF200610017&dbcode=CJFQ&dbname=cjfd2006&v=, 支持协同的3维轻量化模型与圈阅工具的研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJJ200609006&dbcode=CJFQ&dbname=cjfd2006&v=, 基于智能代理的主动式协同服务框架研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JXKX200607030&dbcode=CJFQ&dbname=cjfd2006&v=, 模具数字化制造;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZZXD200605015&dbcode=CJFQ&dbname=cjfd2006&v=, 基于规则和约束的多层递阶产品开发过程管理;http://kns.cnki.net/kcms/detail/detail.aspx?filename=HZLG200510013&dbcode=CJFQ&dbname=CJFD2005&v=, 工作流系统中业务工具动态集成模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJJ200510002&dbcode=CJFQ&dbname=CJFD2005&v=, 产品生命周期管理的访问控制模型研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF200509035&dbcode=CJFQ&dbname=CJFD2005&v=, 产品全生命周期管理在某企业的规划与实施;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSFZ200201005&dbcode=CJFQ&dbname=cjfd2002&v=, 基于PDM的版本管理研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=HZLG200112010&dbcode=CJFQ&dbname=cjfd2001&v=, 企业产品数据管理的实施与应用开发;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJJ200109003&dbcode=CJFQ&dbname=cjfd2001&v=, CIMS环境下产品信息编码原理的研究与应用;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200105019&dbcode=CJFQ&dbname=cjfd2001&v=, 基于PDM的工艺管理研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200401010&dbcode=CJFQ&dbname=CJFD2004&v=, PDM中多资源约束下的项目管理技术;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSGG200410068&dbcode=CJFQ&dbname=CJFD2004&v=, 基于产品结构的工程变更研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=ZGJX200412006&dbcode=CJFQ&dbname=CJFD2004&v=, 产品数据管理中的工程变更管理的建模与实现;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSFZ200402002&dbcode=CJFQ&dbname=CJFD2004&v=, 集成化工艺信息管理系统InteCAPP的研究与开发;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJF200411027&dbcode=CJFQ&dbname=CJFD2004&v=, 基于条件约束满足问题的产品配置研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=JSJJ200411003&dbcode=CJFQ&dbname=CJFD2004&v=, 支持网络建模和仿真的Modelica模型管理框架;http://kns.cnki.net/kcms/detail/detail.aspx?filename=AGLU201307005018&dbcode=CPFD&dbname=CPFD2013&v=, 煤粉O2/CO2气氛下反应动力学及NOx生成与排放的中试研究;http://kns.cnki.net/kcms/detail/detail.aspx?filename=2009145055.nh&dbcode=CMFD&dbname=CMFD2010&v=]