【问题标题】:Scraping a site抓取网站
【发布时间】:2013-03-11 07:29:07
【问题描述】:

我正在尝试编写一个警报系统来定期抓取投诉委员会网站,以查找有关我的产品的任何投诉。我正在使用 Jsoup。下面是给我错误的代码片段。

doc = Jsoup.connect(finalUrl).timeout(10 * 1000).get();

这给了我错误

java.net.SocketException: Unexpected end of file from server

当我在浏览器中复制粘贴相同的 finalUrl 字符串时,它可以工作。然后我尝试了简单的 URL 连接

            BufferedReader br = null;
            try {
                URL a = new URL(finalUrl);
                URLConnection conn = a.openConnection();

                // open the stream and put it into BufferedReader
                br = new BufferedReader(new InputStreamReader(
                        conn.getInputStream()));
                doc = Jsoup.parse(br.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }

但事实证明,连接本身返回 null(br 为 null)。现在的问题是,为什么在浏览器中复制粘贴时相同的字符串会打开站点而没有任何错误?

完整的堆栈跟踪如下:

java.net.SocketException: Unexpected end of file from server
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:774)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:771)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
    at ComplaintsBoardScraper.main(ComplaintsBoardScraper.java:46)

【问题讨论】:

  • 您的网址是否以http:// 开头,您的服务器是否允许连接到端口80
  • @ollo 是的,URL 以 http:// 开头。该服务器是不受我控制的远程服务器。虽然当我在服务器上尝试“nc”命令时,它说:连接到抱怨板.com 80 端口 [tcp/http] 成功!
  • 您的 url 中是否有任何未转义的字符,或者您的应用程序的 Internet 访问是否被阻止?网址是否重定向到另一个网址?
  • @ollo No. URL 似乎格式正确。在将 URL 发送到 Jsoup 之前,我将其 sysout。当我将相同的 URL 从控制台复制粘贴到浏览器时,它会在相同的 url 上打开页面而无需重定向。我正在尝试的 URL 是 complaintsboard.com/…
  • 谢谢,我去看看。

标签: java web-scraping jsoup


【解决方案1】:

那个很棘手! :-)

服务器会阻止所有没有适当的用户代理的请求。这就是为什么您使用浏览器成功但使用 Java 失败的原因。

幸运的是,在 jsoup 中更改用户代理并不是什么大事:

final String url = "http://www.complaintsboard.com/?search=justanswer.com&complaints=Complaints";
final String userAgent = "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)";

Document doc = Jsoup.connect(url) // you get a 'Connection' object here
                        .userAgent(userAgent) // ! set the user agent
                        .timeout(10 * 1000) // set timeout
                        .get(); // execute GET request

我已经使用了我找到的第一个用户代理……我想你也可以使用任何有效的代替。

【讨论】:

  • 我也在考虑类似的问题,但从来没有这么快得到答案。非常感谢。
  • 我一直在考虑将 jsoup 中的用户代理默认为看起来像浏览器的东西,因为这会吸引很多人。对此有何利弊?
  • 这是个好主意,但它有一个缺点:一些网站使用用户代理来决定向用户显示哪个网站(可能是浏览器的“桌面”版本(firefox 等)和智能手机(安卓等)的“移动”版本)。如果您设置“桌面”用户代理,您将解决此处所问的问题。但另一方面,如果一个人除了“移动”版本,他也会得到“桌面”版本。
  • 这里有一些想法:a.) 从本地环境设置中创建一个用户代理,b.) 创建一些默认值,例如为 a台式电脑和一个(或多个)用于移动设备 - 您可以通过阅读所用操作系统的环境来选择正确的一个,c。)为台式机和移动设备创建一个默认值,然后让用户决定他需要哪一个(Jsoup.connect(“url here”).setDesktopUserAgent().get()?)顺便说一句。如果可能的话,如果您在有关此主题的文档中提供一个小提示,这可能会很有用。我想有更多的用户会遇到这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 2014-06-18
相关资源
最近更新 更多