最近写了个爬虫项目,暂时放在github上。https://github.com/shenbaise/goodcrawler
对于爬虫最难的问题应该是javascript和ajax的处理。现在很多网站使用大量ajax,普通爬虫无法获取js生成的
内容。
目前大体上有2中方式来解决这个问题。
一是使用htmlunit之类的所谓handless browser。htmlunit对js支持相当不错。只是适用起来不很方便。想要知道什么时候js执行完了比较困难。
官网 FQA对这个问题的说明。
Nothing happens when using HtmlUnit with AJAX, although page works correctly in browsers. What's wrong?
The main thread using HtmlUnit may be finishing execution before allowing background threads to run. You have a couple of options:
- webClient.setAjaxController(new NicelyResynchronizingAjaxController()); will tell your WebClient instance to re-synchronize asynchronous XHR.
- webClient.waitForBackgroundJavaScript(10000); or webClient.waitForBackgroundJavaScriptStartingBefore(10000); just after getting the page and before manipulating it.
- Explicitly wait for a condition that is expected be fulfilled when your JavaScript runs, e.g.
//try 20 times to wait .5 second each for filling the page. for (int i = 0; i < 20; i++) { if (condition_to_happen_after_js_execution) { break; } synchronized (page) { page.wait(500); } }
我的测试:
public static void testYouku() throws Exception { String url = "http://v.youku.com/v_show/id_XNDc2MDkzMTIw.html"; String xurl = "http://v.youku.com/v_vpofficiallistv5/id_119023280_showid_271942_page_2?__rt=1&__ro=listitem_page2"; // String a = "<a page=\"2\">178-101</a>"; // String url="http://www.baidu.com"; // 模拟一个浏览器 final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17); LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log","org.apache.commons.logging.impl.NoOpLog"); java.util.logging.Logger.getLogger("net.sourceforge.htmlunit").setLevel(java.util.logging.Level.OFF); webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); // final WebClient webClient=new // WebClient(BrowserVersion.FIREFOX_10,"http://myproxyserver",8000); // //使用代理 // final WebClient webClient2=new // WebClient(BrowserVersion.INTERNET_EXPLORER_10); // 设置webClient的相关参数 webClient.getOptions().setJavaScriptEnabled(true); webClient.getOptions().setActiveXNative(false); webClient.getOptions().setCssEnabled(false); webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.waitForBackgroundJavaScript(600*1000); webClient.setAjaxController(new NicelyResynchronizingAjaxController()); webClient.getOptions().setJavaScriptEnabled(true); /* webClient.setJavaScriptTimeout(3600*1000); webClient.getOptions().setRedirectEnabled(true); webClient.getOptions().setThrowExceptionOnScriptError(true); webClient.getOptions().setThrowExceptionOnFailingStatusCode(true); webClient.getOptions().setTimeout(3600*1000); webClient.waitForBackgroundJavaScript(600*1000); */ // webClient.waitForBackgroundJavaScript(600*1000); webClient.setAjaxController(new NicelyResynchronizingAjaxController()); // 模拟浏览器打开一个目标网址 final HtmlPage page = webClient.getPage(url); // 该方法在getPage()方法之后调用才能生效 webClient.waitForBackgroundJavaScript(1000*3); webClient.setJavaScriptTimeout(0); // Thread.sleep(1000 *3L); // String js = "javascript:checkShowFollow('271942','2');"; // ScriptResult sr = page.executeJavaScript(js); // HtmlPage newPage = (HtmlPage) sr.getNewPage(); // System.out.println("new page.asText=" + newPage.asText()); // System.out.println("page.asText=" + page.asText()); // System.out.println("page.getUrl=" + page.getUrl()); List links = (List) page.getByXPath ("//*[@id=\"groups_tab\"]/div[1]/ul/li[1]/a"); if(null!=links){ System.out.println(links.size()); HtmlAnchor link = (HtmlAnchor) links.get(0); System.out.println(link.asXml()); HtmlPage p = link.click(); webClient.waitForBackgroundJavaScript(1000*3L); // webClient.waitForBackgroundJavaScriptStartingBefore(1000L); // Thread.sleep(3000L); System.out.println(p.asText()); } }
youku上面超过100集会拆分多个列表展示,全部是js生成的。
上面代码执行的成功率不是很高。
2013.12.05 19:25:58 Re-synchronized call to http://v.youku.com/v_vpofficiallistv5/id_119023280_showid_271942_page_2?__rt=1&__ro=listitem_page2
2013.12.05 19:26:00 Expected content type of 'application/javascript' or 'application/ecmascript' for remotely loaded JavaScript element at 'http://html.atm.youku.com/html?p=74,75,558,747,753,850,101618,616,101564&ct=h&cs=2224|2210|2209&td=0&s=271942&v=119023280&u=83980375&k=%E7%BD%91%E7%90%83%E7%8E%8B%E5%AD%90|&sid=1386242750138i0r&tt=网球王子 001&pu=http://v.youku.com/v_show/id_XNDc2MDkzMTIw.html&ref=', but got 'text/html'.
其实只要能拿到Re-synchronized call to后面的URL后直接使用httpclient就可以了。但是htmlunit没有提供相关方法。debug了一下源码还是没找到什么时候这个URL被生成的(这个URL肯定是js函数中生成并异步调用的)。
继续研究。。。
第二种方法是使用selenium,jdic直接调用浏览器。
这两种方式都太慢。相对来说第一种方式效率比第二种要好一些。
相关推荐
htmlunit网络爬虫jar包
这个名为“htmlunit爬虫.rar”的压缩包包含了一个基于HTMLUnit的Java爬虫项目,可以用来高效地抓取和分析网络上的数据。 HTMLUnit的核心功能在于其模拟了Web浏览器的行为,包括执行JavaScript、处理cookies、管理...
这个"HtmlUnit爬虫Demo"可能是一个示例项目,展示了如何利用HtmlUnit库进行网络爬虫开发。以下是对HtmlUnit库及其在爬虫中的应用进行的详细说明。 **HtmlUnit简介** HtmlUnit是一个无头浏览器,意味着它没有图形...
在“htmlunit爬虫技术”中,我们将深入探讨如何利用HTMLUnit来实现高效的网络爬虫。 HTMLUnit的核心特性包括: 1. **JavaScript支持**:HTMLUnit能够执行JavaScript代码,这对于许多动态加载内容的现代网站来说至...
高效的java爬虫,内附代码 sql数据表 ,main方法启动。jdk1.8. 有htmlunit的各种获取标签的方法。避免了jsoup无法抓取js代码生成的数据内容的弊端。避免了client无法一次性获取大量信息的弊端。有能获取静态页面形成...
7. **错误处理和异常**:在使用HTMLUnit过程中,可能会遇到各种网络问题和JavaScript错误,需要适当处理这些异常。 ```java try { // 代码可能抛出异常 } catch (FailingHttpStatusCodeException | IOException e)...
使用HTMLUnit开发Java爬虫时,你需要确保你的环境已经安装了JDK 1.8或更高版本,因为这是HTMLUnit和相关依赖库运行的最低要求。一旦环境配置完成,你可以通过添加这些jar文件到你的项目类路径中,或者如果你使用的是...
它被设计为无头浏览器,意味着它可以在没有图形用户界面的情况下运行,这对于网络爬虫和自动化脚本尤其有用。标题"htmlunit-2.15"指的是这个库的特定版本,即2.15版。 HTMLUnit的核心功能在于它的API,它提供了模拟...
同时,了解如何利用它们的优点,以及在遇到问题时如何灵活切换和组合使用,将有助于提高爬虫项目的效率和成功率。在实际工作中,结合阅读相关的博客(如提供的博文链接),可以深入了解这些工具的实际应用案例和最佳...
基于Apache Nutch 1.8和Htmlunit组件,实现对于AJAX加载类型页面的完整页面内容抓取解析。 According to the implementation of Apache Nutch 1.8, we can't get dynamic ...
本文将讲解如何使用JAVA语言和HtmlUnit爬虫工具模拟登陆CSDN网站。HtmlUnit是一个基于JAVA的爬虫工具,能够模拟浏览器的行为,从而实现自动化的爬虫操作。 在本案例中,我们首先需要引入HtmlUnit和Jsoup的依赖项,...
HTMLUnit是一个功能强大的Java库,它模拟了一个无头Web浏览器,允许开发者进行自动化网页测试和网络爬虫工作。这个库的核心在于它能够解析HTML、执行JavaScript,并与网页上的元素进行交互,而无需真实地打开一个...
HTMLUnit是一个强大的Java库,它模拟了一个无头Web浏览器,主要用于自动化测试和网页抓取。在版本2.23的zip文件中,我们主要关注HTMLUnit的核心功能和它如何帮助开发者处理HTML内容。 HTMLUnit的核心是基于Jakarta ...
这个库对于自动化测试、数据抓取和网页爬虫项目非常有用。标题提到的“htmlunit依赖jar包”是指为了正确运行HTMLUnit,你需要的一系列Java类库。 首先,`htmlunit-2.9.jar`是HTMLUnit的核心库文件,包含了HTMLUnit...
4. **异常处理**:考虑到网络问题和页面动态性,应适当地处理可能出现的异常。 5. **资源管理**:爬虫结束后,记得关闭`WebClient`以释放系统资源。 综上所述,HTMLUnit是一个强大的Java爬虫工具,它提供了全面的...
总的来说,HtmlUnit 2.30为开发者提供了一种高效、灵活的工具,用以处理Web测试和爬虫任务,尤其是在需要处理JavaScript动态内容的场景下。尽管自2018年以来,HtmlUnit可能已经更新了更多版本,但2.30版本仍然是一个...
这对于自动化测试、数据抓取和无头爬虫来说非常有用。由于其无头特性,HTMLUnit在服务器端或命令行环境中运行特别高效。 在实际应用中,一个典型的HTMLUnit程序可能包括以下步骤: 1. 创建`HtmlUnitWebClient`实例...
【标题】"基于Apache Nutch和Htmlunit的扩展实现AJAX页面爬虫抓取解析插件.zip" 提供了一个深入的爬虫项目实例,旨在解决AJAX动态网页内容的抓取问题。Apache Nutch是一个开源的网络爬虫框架,而Htmlunit是一个无头...
总结起来,这个"htmlunit爬取动态页面包"提供了一整套工具,使得开发者能够编写出能够处理动态内容的Java网络爬虫,通过集成的JavaScript引擎和对HTML的深入解析,实现了高效、全面的数据采集能力。