使用 JSOUP 抓取网页并给出 SSL 错误。这是站点特定问题吗? (JSOUP 适用于其他网站)

Scraping A Webpage With JSOUP and Given An SSL Error. Is This A Site Specific Issue? (JSOUP Works On Other Websites)

使用 JSOUP 抓取网页并给出 SSL 错误。这是站点特定问题吗? (JSOUP 适用于其他网站)

我正在尝试运行刮擦,我一直运行这样刮擦,但是这次失败了。 一般我都是用jsoup连接一个网页,然后在页面上抓取我想要的东西。这个似乎在尝试进行 ssl 握手或其他操作,但失败了。

我发现 this page 有类似的问题,但是,我认为 op 在所有 jsoup 抓取上都有这个问题,我的问题是针对这个网站的。 https://www.strack.de/de/shop/?idm=1162&d=1&idmp=94&spb=MTQ7NzQ7MTI0OzEyMzY7 我在这个网站上尝试了多个页面,但都有同样的问题。但是,我尝试过的所有其他网站根本没有这个问题并且可以正常抓取。

我尝试安装最新版本的 java 并重新启动电脑,这并没有导致 ssl 连接成功。我还尝试进入 Firefox 并下载认证。这似乎与答案中描述的路径不同。

"more info" > "security" > "show certificate" > "details" > "export.."

我认为这个问题可能是由另一个问题引起的,因为抓取工具在其他网站上运行良好。这就是为什么我将其创建为一个单独的问题而不是对该问题的评论。

这是我尝试下载证书时发生的情况。 没有显示证书,而是查看证书,它没有详细信息选项,也没有导出选项。 Trying to get the .cert file, no prompt

我是不是做错了什么导致握手,或者这是某种不允许在这个网站上抓取的功能?我试图从这个网页上刮掉定价: https://www.strack.de/de/shop/?idm=1162&d=1&idmp=94&spb=MTQ7NzQ7MTI0OzEyMzY7

我使用 JSOUP 尝试抓取此页面。 它给了我一个错误。当我用谷歌搜索时,它似乎是人们在尝试连接到服务器时遇到的错误。

它给了我这个错误:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153) at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:732) at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:707) at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:297) at org.jsoup.helper.HttpConnection.get(HttpConnection.java:286) at scrapetestforstack.de.ScrapeTestForStackDe.main(ScrapeTestForStackDe.java:81) Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491) ... 15 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ... 21 more C:\Users\LeonardDME\AppData\Local\NetBeans\Cache.2\executor-snippets\run.xml:53: Java returned: 1 BUILD FAILED (total time: 0 seconds)

这是我正在尝试执行的代码。


//第 3 阶段为 UrlsURL 抓取
文档 doc = Jsoup.connect(URL).get();

   title = doc.title();
                    
         TitleFixer = title.replaceAll(" ", "");
         title = TitleFixer.replaceAll("|", "");
         TitleFixer = title.replaceAll("|", "");
        title = TitleFixer.replaceAll(";", "");
   
  //Set file writing stuff 1
            GimmeAName = ("C:\Users\LeonardDME\Documents\NetBeansProjects\ScrapeTestForStackDe\Urls\" + title + ".csv");    
    File f = new File(GimmeAName);
    FileWriter fw = new FileWriter(f);
    PrintWriter out = new PrintWriter(fw);    
            StuffToWrite = URLArray[counter];
            // fetch the document over HTTP               
                 Elements spangrabbers = doc.getElementsByClass("art_orginal_preis142790");
                   for (Element spangrab : spangrabbers)
        {
        //System.out.println("New Span: ");
        //System.out.println(spangrab);
        holder2 = spangrab.text();
        //System.out.println(holder2);
        SpanHolderArray[SpanHolderCounter] = holder2;
        SpanHolderCounter++;
        }
            // get all links in page
            Elements links = doc.select("a[href]");
            for (Element link : links) {
                // get the value from the href attribute
                checker = link.attr("href");
                if (checker.contains("http"))
                {
                }
                else if(checker.contains("javascript"))
                {
                }
                else if(checker.contains("style"))
                {
                }
                else
                {
                    counter++;

                    if(LinkContorter == null && LinkContorter.isEmpty())
                    {
                        //do nothing
                    }
                    else
                    {
                        System.out.println(LinkContorter);
                        out.print(LinkContorter);
                        out.print(",");
                        out.print("\n");
                        //Flush the output to the file
                        out.flush();
                    }
                }
            }
            System.out.println(counter);
        //Close the Print Writer
       out.close();       
       //Close the File Writer
       fw.close();

有没有可能你们中的一些人可以尝试抓取这个网站,看看你们是否得到了和我一样的结果?我怀疑可能有一些防止抓取的安全措施,但是,我不想放弃这个任务,除非我知道情况确实如此。几个月前的二月或三月,我也曾经毫无问题地抓取过同一个网站。

如果您不发送任何敏感数据,您可以稍微作弊并配置您自己的 TrustManger 以接受所有内容。

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
    }

    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
    }
} };

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

现在它将用于每个连接,因此不推荐使用。相反,您可以注释掉最后一行,并通过指定 SSLSocketFactory 使 jsoup 仅将其用于单个连接:

// HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // not needed anymore
Document doc = Jsoup.connect(URL)
                    .sslSocketFactory(sc.getSocketFactory())
                    .get();

虽然 Firefox 显示此服务器使用的证书确实使用中间 CA Sectigo RSA Domain Validation Secure Server CA 和根 CA USERTrust RSA Certification Authority 进行验证,但服务器仅发送叶证书而不发送中间证书 'chain' 标准要求的证书。

您可以通过查看 SSLLabs test report; notice the orange warning in the summary and this near the bottom of the cert details box 来了解这一点。或者,如果您拥有(或获得)OpenSSL openssl s_client -connect www.strack.de:443 -showcerts(如今许多服务器需要 SNI,对于低于 1.1.1 的 OpenSSL 发送 SNI,您需要添加 -servername $host 而不是 this 服务器),或者因为你有 Java keytool -printcert -sslserver www.strack.de.

省略所需的链证书是懒得阅读文档的服务器管理员的一个常见错误,因为如果他们只使用一两个浏览器进行测试,他们不会注意到这个错误——浏览器通常可以解决缺少的链证书,但大多数其他软件,包括 Java,默认情况下不能或不能。它不太可能被用作故意的反抓取措施,因为它很容易被绕过,请参阅下一页,但它确实表明服务器管理员没有实际目标或兴趣 支持协助抓取。

而不是忽略 所有 证书问题,因为 您可以通过获取链证书来解决这个问题——例如通过从 Firefox 导出或通过获取证书 http://crt.sectigo.com/SectigoRSADomainValidationSecureServerCA.crt 中的 caIssuer link(在 SSLLabs 报告或 keytool -printcert 解码中显示,或者如果您 运行 openssl s_client 输出到 openssl x509 -noout -text) -- 并将其添加到您的信任库(默认情况下文件 $JREDIR/lib/security/cacertsjssecacerts 除非您使用 sysprop 或代码更改它)。

(已添加)Re Firefox,您已经发现 UI 在您 link 编辑的 Q 之后的几年中发生了细微变化:您现在单击挂锁,然后单击右箭头、更多信息、查看证书。要导出特定证书,请单击“Sectigo RSA ...”选项卡并向下滚动到一半: 然后单击“PEM(cert)”并保存在适当的位置。

您也可以将此问题报告给站点管理员或所有者。他们是否会关心你或一般的非浏览器访问我不知道。