htmlunit抓取动态网页( JSoup依赖:2、使用模拟浏览器方式获取动态页面使用)
优采云 发布时间: 2021-11-15 12:12htmlunit抓取动态网页(
JSoup依赖:2、使用模拟浏览器方式获取动态页面使用)
<br /> <br /> org.apache.httpcomponents<br /> httpclient<br /> 4.5.2<br /> <br />
JSoup 取决于:
<br /> <br /> <br /> org.jsoup<br /> jsoup<br /> 1.10.3<br /> <br />
<br />[color=red]<br />此处需要特别强调,对于很多网站,对爬虫都有一定的防范,因此在获取页面时,必须要补齐浏览器信息,否则很容易会导致被封IP!<br />[/color]<br />
2、使用模拟浏览器方式获取动态页面
使用模拟浏览器真的很无奈,因为这种方法确实很慢,但是对于异步加载内容的网页来说特别有效。只有在发现无法直接通过Http拉取页面获取元素值时,才能使用此方法。
HtmlUnit 获取网页:
<br /> /**<br /> * 通过模拟浏览器的方式下载完整页面。<br /> * <br /> * @param url<br /> * @return<br /> * @throws FailingHttpStatusCodeException<br /> * @throws IOException<br /> */<br /> public static String downloadHtml(String url, int timeout)<br /> throws FailingHttpStatusCodeException, IOException {<br /> try (final WebClient webClient = new WebClient(BrowserVersion.CHROME)) {<br /> webClient.getOptions().setJavaScriptEnabled(true);<br /> webClient.getOptions().setCssEnabled(false);<br /> webClient.getOptions().setRedirectEnabled(true);<br /> webClient.getOptions().setThrowExceptionOnScriptError(false);<br /> webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);<br /><br /> webClient<br /> .setAjaxController(new NicelyResynchronizingAjaxController());<br /> webClient.getOptions().setTimeout(timeout);<br /><br /> WebRequest webRequest = new WebRequest(new URL(url));<br /> webRequest.setHttpMethod(HttpMethod.GET);<br /> final HtmlPage page = webClient.getPage(webRequest);<br /> webClient.waitForBackgroundJavaScriptStartingBefore(500);<br /> webClient.waitForBackgroundJavaScript(20000);<br /><br /> final String pageAsXml = page.asXml();<br /><br /> return pageAsXml;<br /> }<br /> }<br />
HtmlUnit 取决于:
<br /> <br /> net.sourceforge.htmlunit<br /> htmlunit<br /> 2.30<br /> <br />
常见问题二:如何避免IP被封
处理方法比较简单,就是不使用并发,或者长时间连续抓取网站的内容。爬行时最好保持一定的时间间隔。根据我爬不同网站的经验,每3-5秒获取一个网页是最安全的。有些网站的IP一旦被封,可能需要一周左右的时间才能解锁,所以对于有固定外网IP的用户来说,在进行*敏*感*词*爬取之前一定要注意这个限制。
以下爬取代码供参考:
<br /> /*<br /> * (non-Javadoc)<br /> * <br /> * @see<br /> * com.hna.tech.spider.service.SpiderService#setPageArticleDetail(java.lang<br /> * .String)<br /> */<br /> public List setPageArticleDetail(<br /> List pageList) throws IOException,<br /> InterruptedException {<br /> for (Map item : pageList) {<br />[color=red]<br /> // 最小延迟3秒,少于3秒将可能被封IP<br /> Thread.sleep(3000);<br />[/color]<br /> String articleUrl = item.get(KEY_LINK);<br /> Document doc = getArticleDocument(articleUrl);<br /><br /> String articleHtml = getArticleContentHtml(doc);<br /> item.put(KEY_CONTENT_HTML, articleHtml);<br /><br /> String articleContent = getArticleContent(doc);<br /> item.put(KEY_CONTENT, articleContent);<br /> }<br /><br /> return pageList;<br /> }<br />
那么如何提高爬取效率呢?一般网站无论是DDOS攻击还是恶意网页扫描都会根据Session和IP加锁,所以问题很简单。请求通过多个线程发起,保证每个Session请求的时间间隔。另外,不要太并发,只要不对网站造成压力,IP一般不会被阻塞。
常见问题三:元素选择问题
获取元素的方式有很多种,可以通过ID、CSS样式、元素类型(比如
) 等根据个人喜好,通常可以获取元素的内容,例如文章标题,文章正文等。
下面分享我个人使用JSoup获取页面元素内容的一些经验。
1、 分步获取
即先获取顶级节点,比如文章的内容的顶级节点,然后先获取第一个顶级节点,再通过获取低级节点的内容JSoup,避免在有多个节点时获取访问的内容超出预期。
2、CSS 样式的选择
当有多个类样式时,例如:
...
, 使用JSoup选择:
<br />doc.select("div.css1.css2")<br />
使用点将它们连接在一起。