java爬虫抓取动态网页(Java爬虫遇到需要登录的网站,该怎么办还是反向解析法呢)

优采云 发布时间: 2021-11-18 02:03

  java爬虫抓取动态网页(Java爬虫遇到需要登录的网站,该怎么办还是反向解析法呢)

  这是 Java 爬虫系列博文中的第三篇。Java爬虫遇到上一篇需要登录的网站怎么办?在本文中,我们简要说明了爬虫遇到的登录问题的解决方案。在这个文章中,我们来谈谈遇到爬虫时数据异步加载的问题。这也是爬虫常见的问题。

  现在很多都是前后端分离的项目,这会让数据异步加载的问题更加突出,所以在爬取的时候遇到这样的问题不要惊讶,不要慌。一般来说,这种问题有两种解决方案:

  1、内置浏览器内核

  内置浏览器就是在爬虫程序中启动一个浏览器内核,这样我们就可以拿到js渲染出来的页面,这样我们就和采集的静态页面一样了。此类常用工具有以下三种:

  这些工具可以帮助我们解决异步数据加载的问题,但它们都有缺陷,即效率低下且不稳定。

  2、逆向分析法

  什么是逆向分析?我们js渲染页面的数据是通过Ajax从后端获取的。我们只需要找到对应的ajax请求连接就可以了,这样我们就可以获取到我们需要的数据了。逆向分析法的优点是通过这种方式得到。数据都是json格式,解析起来也比较方便。另一个优点是界面变化的概率相对于页面来说更小。它也有两个缺点。一是在使用Ajax时需要耐心和熟练,因为需要在一个大的推送请求中找到自己想要的东西,二是对JavaScript渲染的页面无能为力。

  以上是异步数据加载的两种解决方案。为了加深大家的理解以及如何在项目中使用,我以采集网易新闻为例。网易新闻地址:. 使用两种申诉方式获取网易新闻的新闻列表。网易新闻如下:

  

  内置浏览器Selenium方式

  Selenium 是一种模拟浏览器进行自动化测试的工具。它提供了一组 API 来与真正的浏览器内核进行交互。常用于自动化测试,常用于解决爬虫时的异步加载。如果我们想在我们的项目中使用Selenium,我们需要做两件事:

  

org.seleniumhq.selenium

selenium-java

3.141.59

   System.getProperties().setProperty("webdriver.chrome.driver", "chromedriver.exe");

  完成以上两步后,我们就可以编写和使用Selenium采集网易新闻了。具体代码如下:

  /**

* selenium 解决数据异步加载问题

* https://npm.taobao.org/mirrors/chromedriver/

*

* @param url

*/

public void selenium(String url) {

// 设置 chromedirver 的存放位置

System.getProperties().setProperty("webdriver.chrome.driver", "chromedriver.exe");

// 设置无头浏览器,这样就不会弹出浏览器窗口

ChromeOptions chromeOptions = new ChromeOptions();

chromeOptions.addArguments("--headless");

WebDriver webDriver = new ChromeDriver(chromeOptions);

webDriver.get(url);

// 获取到要闻新闻列表

List webElements = webDriver.findElements(By.xpath("//div[@class='news_title']/h3/a"));

for (WebElement webElement : webElements) {

// 提取新闻连接

String article_url = webElement.getAttribute("href");

// 提取新闻标题

String title = webElement.getText();

if (article_url.contains("https://news.163.com/")) {

System.out.println("文章标题:" + title + " ,文章链接:" + article_url);

}

}

webDriver.close();

}

  运行这个方法,得到如下结果:

  

  我们已经使用Selenium正确提取了网易新闻列表。

  逆向分析

  逆向分析方法是通过ajax异步获取链接获取数据,直接获取新闻数据。如果没有技巧,找Ajax的过程会很痛苦,因为一个页面加载的链接太多,看看网易新闻的网络:

  

  有数百个请求,我如何找到哪个请求获取新闻数据?不嫌麻烦的话,可以一一去点,绝对能找到。另一种快速的方法是使用网络的搜索功能。如果你不知道搜索按钮,我在上图中圈出了它。只需在新闻中复制一个新闻标题,然后搜索,即可得到结果,如下图所示:

  

  这样我们就快速的获取到了重要新闻数据的请求链接,链接为:访问链接,查看链接返回的数据,如下图:

  

  从数据上可以看出,我们需要的数据都在这里了,所以我们只需要解析这一段数据。从这条数据中解析新闻标题和新闻链接有两种方式,一种是正则表达式,另一种是将数据转成json或者list。这里我选择第二种方法,使用fastjson将返回的数据转换成JSONArray。所以我们要引入fastjson,并在pom.xml中引入fastjson依赖:

  

com.alibaba

fastjson

1.2.59

  除了引入fastjson依赖之外,我们还需要对转换前的数据进行简单的处理,因为当前数据不符合list的格式,需要去掉data_callback(也是最后一个)。获取网易新闻的具体逆向分析代码如下:

  /**

* 使用反向解析法 解决数据异步加载的问题

*

* @param url

*/

public void httpclientMethod(String url) throws IOException {

CloseableHttpClient httpclient = HttpClients.createDefault();

HttpGet httpGet = new HttpGet(url);

CloseableHttpResponse response = httpclient.execute(httpGet);

if (response.getStatusLine().getStatusCode() == 200) {

HttpEntity entity = response.getEntity();

String body = EntityUtils.toString(entity, "GBK");

// 先替换掉最前面的 data_callback(

body = body.replace("data_callback(", "");

// 过滤掉最后面一个 )右括号

body = body.substring(0, body.lastIndexOf(")"));

// 将 body 转换成 JSONArray

JSONArray jsonArray = JSON.parseArray(body);

for (int i = 0; i < jsonArray.size(); i++) {

JSONObject data = jsonArray.getJSONObject(i);

System.out.println("文章标题:" + data.getString("title") + " ,文章链接:" + data.getString("docurl"));

}

} else {

System.out.println("处理失败!!!返回状态码:" + response.getStatusLine().getStatusCode());

}

}

  编写main方法,执行上面的方法。需要注意的地方是:这个时候传入的链接不是。得到以下结果:

  

  两种方法都成功获取了网易新闻异步加载的新闻列表。对于这两种方法的选择,我个人更倾向于使用逆向分析法,因为它的性能和稳定性比浏览器内置内核更可靠。但是,对于一些使用 JavaScript 片段渲染的页面,内置浏览器更可靠。所以要根据具体情况来选择。

  希望这篇文章对你有帮助,下一篇是关于爬虫IP被封的问题。如果你对爬虫感兴趣,不妨关注一波,互相学习,互相进步

  源代码:源代码

  文章希望大家多多指教,共同学习,共同进步

  最后

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线