如何使用 Jsoup 抓取 Google 个 SERP?

How to scrape Google SERPs with Jsoup?

我试图使用 600 次不同的搜索从 google 中抓取链接,在此过程中我开始收到以下错误。

错误

org.jsoup.HttpStatusException: HTTP error fetching URL. Status=503, URL=http://ipv4.google.com/sorry/IndexRedirect?continue=http://google.com/search/...


现在我已经完成了我的研究,它发生是因为 google 学者禁令限制你进行有限的搜索并且需要解决 captch 才能继续,而 jsoup 做不到。

代码

Document doc = Jsoup.connect("http://google.com/search?q=" + keyWord)
.userAgent("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
.timeout(5000)
.get();


互联网上的答案非常模糊,没有提供明确的解决方案,有人提到 cookie 可以解决这个问题,但没有说 "how" 可以做到这一点。

改进抓取的一些提示:

1。使用代理

代理可以让您减少被验证码抓住的机会。根据您的平均结果集,您应该使用 50 到 150 个代理。这里有两个网站可以提供一些代理:SEO-proxies.com or Proxify Switch Proxy.

// Setup proxy
String proxyAdress = "1.2.3.4";
int proxyPort = 1234;
Proxy proxy = new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(proxyAdress, proxyPort))

// Fetch url with proxy
Document doc = Jsoup //
               .proxy(proxy) //
               .userAgent("Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2") //
               .header("Content-Language", "en-US") //
               .connect(searchUrl) //
               .get();

2。验证码

如果无论如何,您被验证码捕获了,您可以使用一些在线验证码解决服务(Bypass Captcha, DeathByCaptcha 仅举几例)。以下是自动解决验证码的通用分步过程:

  • 检测验证码错误页面

--

try {

  // Perform search here...

} catch(HttpStatusException e) {
    switch(e.getStatusCode()) {
        case java.net.HttpURLConnection.HTTP_UNAVAILABLE:
            if (e.getUrl().contains("http://ipv4.google.com/sorry/IndexRedirect?continue=http://google.com/search/...")) {
               // Ask online captcha service for help...
            } else {
               // ...
            }
        break;

        default:
        // ...
    } 
}
  • 下载验证码图像(CI)

--

Jsoup                     //
//.cookie(..., ...)       // Some cookies may be needed...
.connect(imageCaptchaUrl) //
.ignoreContentType(true)  // Needed for fetching image
.execute()                //
.bodyAsBytes();           // byte[] array returned...
  • 在线发送CI到在线验证码服务

--

这部分依赖于验证码服务API。您可以在这篇 8 best captcha solving services 文章中找到一些服务。

  • 等待响应...(1-2 秒为佳)
  • 用响应填写表格并用 Jsoup 发送

    Jsoup FormElement is a life saver here. See this 了解详情。

3。其他一些提示

Hints for Google scrapers 文章可以为您提供更多改进代码的指导。您会发现此处提供的前两个提示以及更多提示:

  • Cookies:在每次 IP 更改时清除它们或根本不使用它们
  • Threads: 你不应该打开两个连接。 Firefox limits itself to 4 connections 每个代理。
  • 返回的结果:将&num=100附加到您的url以发送更少的请求
  • 请求率:让您的请求看起来像人。每个 IP 每 24 小时发送的请求不应超过 500 个。

参考资料:

作为 Stephan 回答的替代方法,您可以使用此程序包获得 Google 搜索结果,而无需代理。代码示例:

Map<String, String> parameter = new HashMap<>();
parameter.put("q", "Coffee");
parameter.put("location", "Portland");
GoogleSearchResults serp = new GoogleSearchResults(parameter);

JsonObject data = serp.getJson();
JsonArray results = (JsonArray) data.get("organic_results");
JsonObject first_result = results.get(0).getAsJsonObject();
System.out.println("first coffee: " + first_result.get("title").getAsString());

Project Github