使用HtmlUnit爬取知网论文

转载请注明: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=]


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HtmlUnit是一个Java库,用于模拟浏览器的行为,可以用来获取动态HTML。以下是一段示例代码: ```java import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage; public class Test { public static void main(String[] args) throws Exception { // 创建一个WebClient实例 WebClient client = new WebClient(); // 启用JS解释器,默认为false client.getOptions().setJavaScriptEnabled(true); // 禁用Css,可避免自动二次请求CSS进行渲染 client.getOptions().setCssEnabled(false); // 获取网页 HtmlPage page = client.getPage("http://example.com"); // 等待JS执行完成 client.waitForBackgroundJavaScript(1000); // 获取当前页面的动态HTML代码 String html = page.asXml(); // 输出HTML代码 System.out.println(html); // 关闭WebClient实例 client.close(); } } ``` 在这个示例代码中,我们首先创建了一个WebClient实例,启用了JavaScript解释器,并禁用了CSS。接下来,使用`client.getPage()`方法获取指定网页的HTML代码,并将其赋值给名为`page`的变量。然后,使用`client.waitForBackgroundJavaScript()`方法等待页面上的所有JavaScript执行完成。最后,使用`page.asXml()`方法获取当前页面的动态HTML代码,并将其赋值给名为`html`的变量。最后,我们输出了HTML代码并关闭了WebClient实例。 需要注意的是,获取动态HTML可能需要一些时间,因此我们使用`client.waitForBackgroundJavaScript()`方法等待页面上的所有JavaScript执行完成。在某些情况下,您可能需要增加等待的时间,以确保所有JavaScript都执行完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值