通过 Jsoup 下载的网页源代码不等于实际的网页源代码。

4
我是一名有用的助手,可以为您翻译文本。
我有一个严重的问题。我已经在Stack Overflow和许多其他网站上搜索了很久。无论哪里都给出了相同的解决方案,但我尝试了所有这些方法,仍然无法解决此问题。
我有以下代码:
Document doc = Jsoup.connect(url).timeout(30000).get();

我使用Jsoup库,但是得到的结果与我们可以看到的页面源代码不相等。如果右键单击页面- >页面源,则会缺少许多部分。使用上述代码行得到的结果中缺少了许多内容。

在Google上搜索了一些网站后,我发现了这种方法:

URL url = new URL(webPage);
        URLConnection urlConnection = url.openConnection();
        urlConnection.setConnectTimeout(10000);
        urlConnection.setReadTimeout(10000);
        InputStream is = urlConnection.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);



        int numCharsRead;
        char[] charArray = new char[1024];
        StringBuffer sb = new StringBuffer();
        while ((numCharsRead = isr.read(charArray)) > 0) {
            sb.append(charArray, 0, numCharsRead);
        }
        String result = sb.toString();          

        System.out.println(result);   

但是没有运气。 当我在互联网上搜索这个问题时,我看到许多网站都说我需要在下载网页源代码时设置正确的charSet和编码类型。但是我怎么能从我的代码动态地知道这些东西呢?Java中是否有任何类可以做到这一点?我也稍微研究了crawler4j,但它对我来说并没有太大帮助。请帮忙各位。我已经被这个问题困扰了一个多月,尝试了我所能想到的所有方法。所以最后的希望寄托在stack overflow的神明身上,他们总是有所帮助!!


也许页面源代码是格式不正确的HTML,JSoup正在通过删除无效部分来清理它? - dnault
嗨dnault,该网页来自一个良好托管的网站,因此我认为它已经通过了验证,可能不是格式不正确的HTML。 - Vasanth Nag K V
3个回答

5
我最近遇到了这个问题。我遇到了某种机器人保护措施。将您的原始行更改为:
Document doc = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0")
                    .timeout(30000)
                    .get();

太棒了!!很不错的实用技巧!我曾经花费了很多时间学习Selenium、Maven等东西,没想到使用Jsoup居然有这么简单的解决方案。而且你提供的方法对我的效率提升非常大,但是学习所有这些超级技巧对我来说也是一次愉快的经历!非常感谢! - Vasanth Nag K V
嗨cftygv,你回答了我的上面的问题,你的解决方案很好用。但现在当我把你的解决方案应用到另一个网站时,我再次遇到了相同的问题。 - Vasanth Nag K V

3
问题可能是你的网页由在浏览器中运行的Javascript渲染,JSoup无法解决这个问题,因此你可以尝试使用HtmlUnit来模拟浏览器:使用Jsoup登录并爬取数据更新 HTML不同的原因有几个。最有可能的是,此网页包含<javascript>元素,其中包含动态页面逻辑。这可能是您网页内的应用程序,它会向服务器发送请求,并根据响应添加或删除内容。
JSoup永远不会呈现这样的页面,因为这是Chrome、Firefox或IE等浏览器的工作。JSoup是一个轻量级的解析器,用于从服务器获取纯文本html。
因此,您可以使用Web驱动程序来模拟Web浏览器并在内存中呈现页面,使其具有与向用户显示的内容相同的内容。您甚至可以使用此驱动程序进行鼠标点击。

所提出的Web驱动程序的实现在链接答案中是HtmlUnit。它是最轻量级的解决方案,但可能会给您带来意外的结果:Selenium vs HtmlUnit?

如果您想要最真实的页面呈现,您可能需要考虑Selenium WebDriver


嗨,安德烈,你能详细解释一下吗?我对你给我的链接不是很理解。我刚开始使用Jsoup,所以对它的功能不是很熟悉。很想了解更多。 :) - Vasanth Nag K V
更新 - HtmlUnit 现在可以使用 WebDriver。 - Andrey Chaschev
安德烈,我能知道你提到的这个Web驱动程序是什么吗?它是一个可以在我的Java程序中使用,并在Java程序中代替Web浏览器完成工作的程序吗?请解释一下“模拟Web浏览器并在内存中呈现页面”的Web驱动程序以及“使用此驱动程序进行鼠标点击”的含义。 - Vasanth Nag K V
感谢您的帮助,Andrey。您有没有关于如何在我的代码中使用这些Web驱动程序的想法?有任何API吗?我猜流程应该是这样的:Java代码-> WebDriver->渲染页面->获取结果->使用Jsoup解析。如果我错了,请纠正我。 - Vasanth Nag K V
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/41132/discussion-between-user2781031-and-andrey-chaschev - Vasanth Nag K V
显示剩余5条评论

1

为什么要以这种方式解析网页?如果网站上有可用的消费服务,则该网站可能具有 REST API

回答你的问题,使用 Web 浏览器查看的网页 可能 与使用 URLConnection 下载的同一网页不同。

以下可能是导致这些差异的原因:

  1. 请求头:当客户端(Java应用程序/浏览器)请求URL时,它会设置各种标题作为请求的一部分,Web服务器可能会相应地更改响应内容。

  2. JavaScript:一旦收到响应,如果响应中存在JavaScript元素,则被浏览器的JavaScript引擎执行,这可能会更改DOM的内容。

  3. 浏览器插件,例如IE浏览器辅助对象,Firefox扩展或Chrome扩展,可能会更改DOM的内容。

简单来说,使用URLConnection请求URL时,您会接收到原始数据,但是使用浏览器地址栏请求相同的URL时,您会得到经过处理(由JavaScript/浏览器插件)的网页。

URLConnection/JSoup可以让您根据需要设置请求头,但由于第2和第3点,您仍然可能会得到不同的响应。Selenium允许您远程控制浏览器,并具有访问渲染页面的API。Selenium用于Web应用程序的自动化测试。


嗨,Vasanth,请按照我在你下面的答案中的评论进行操作,我已经与Andrey谈论了我所面临的问题。我也尝试了Selenium,但仍然没有运气,非常感谢你对我的问题的关注。 - Vasanth Nag K V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接