是否可以通过okHttpClient模仿浏览器?
Is it possible to imitate browser via okHttpClient?
我正在努力抓取一个有验证码的网站,example of the page。我发现,当使用 Selenium Chromedriver 验证码时,必须只输入一次,之后我可以在不获取验证码的情况下加载页面。但是通过 Selenium 抓取数据非常慢,而且通常使用起来真的很痛苦,所以我尝试了另一种方法。我只在 selenium 中加载任何页面一次,输入验证码并使用
保存 chrome cookie
Set<Cookie> cookies = chromeDriver.manage().getCookies();
之后,我将这组 Cookie 传递给我的请求构建器方法
private Request buildRequest(String url, Set<Cookie> cookies) {
Iterator<Cookie> iterator = cookies.iterator();
StringBuilder cookieSb = new StringBuilder();
while (iterator.hasNext()) {
Cookie cookie = iterator.next();
cookieSb.append(cookie.getName() + "=" + cookie.getValue() + "; ");
}
String cookie = cookieSb.toString();
cookie = cookie.substring(0, cookie.length() - 2);
return new Request.Builder()
.url(url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36")
.header("Cookie", cookie)
.build();
}
然后通过okHttp3Client执行这个请求
private Response getResponse(Request request) throws IOException {
return client.newCall(request).execute();
}
如果没有传递cookies或者有错误的cookies,那么立即captha响应返回给这样的请求,所以我可以说这个方法在某种程度上是有效的。然而,在执行了一些请求后,我再次获得验证码,如果我在 chromedriver 中重新加载页面,也会有验证码。我无法发现显示 capthca 的模式,它总是需要不同数量的请求和从第一个请求到最后一个请求的时间。我试过在请求之间设置超时,但没有帮助。除了请求中的 cookie 之外,我还尝试了 headers 的不同组合。我已经尝试从不同的 chrome windows 获得 100 个有效的 cookie 并遍历它们,它们很快就会得到验证码。我试过调试 chromedriver 内部 okhttp 调用,复制它的逻辑,但它似乎没有直接向网站发出请求并且隐藏得很好。
我错过了什么吗?有没有办法改进我的请求 object,所以我总是在没有验证码的情况下得到响应?
您可以使用 CookieStore,以防他们在 session 期间更新您的 cookie。这将取代将 http cookie 设置为 headers。但会适应任何 Set-Cookie 响应 headers.
https://whosebug.com/a/35346473/1542667
但他们可以并且可能会使用其他信号,例如传入请求率,这些信号看起来不像人类在使用该网站。
但是您正在与一个网站进行猫捉老鼠的游戏,该网站完全不希望您抓取他们的内容。
FWIW 我希望他们赢得这场战斗,在这种情况下你是“坏演员”。无论如何,祝你好运。
我正在努力抓取一个有验证码的网站,example of the page。我发现,当使用 Selenium Chromedriver 验证码时,必须只输入一次,之后我可以在不获取验证码的情况下加载页面。但是通过 Selenium 抓取数据非常慢,而且通常使用起来真的很痛苦,所以我尝试了另一种方法。我只在 selenium 中加载任何页面一次,输入验证码并使用
保存 chrome cookieSet<Cookie> cookies = chromeDriver.manage().getCookies();
之后,我将这组 Cookie 传递给我的请求构建器方法
private Request buildRequest(String url, Set<Cookie> cookies) {
Iterator<Cookie> iterator = cookies.iterator();
StringBuilder cookieSb = new StringBuilder();
while (iterator.hasNext()) {
Cookie cookie = iterator.next();
cookieSb.append(cookie.getName() + "=" + cookie.getValue() + "; ");
}
String cookie = cookieSb.toString();
cookie = cookie.substring(0, cookie.length() - 2);
return new Request.Builder()
.url(url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36")
.header("Cookie", cookie)
.build();
}
然后通过okHttp3Client执行这个请求
private Response getResponse(Request request) throws IOException {
return client.newCall(request).execute();
}
如果没有传递cookies或者有错误的cookies,那么立即captha响应返回给这样的请求,所以我可以说这个方法在某种程度上是有效的。然而,在执行了一些请求后,我再次获得验证码,如果我在 chromedriver 中重新加载页面,也会有验证码。我无法发现显示 capthca 的模式,它总是需要不同数量的请求和从第一个请求到最后一个请求的时间。我试过在请求之间设置超时,但没有帮助。除了请求中的 cookie 之外,我还尝试了 headers 的不同组合。我已经尝试从不同的 chrome windows 获得 100 个有效的 cookie 并遍历它们,它们很快就会得到验证码。我试过调试 chromedriver 内部 okhttp 调用,复制它的逻辑,但它似乎没有直接向网站发出请求并且隐藏得很好。
我错过了什么吗?有没有办法改进我的请求 object,所以我总是在没有验证码的情况下得到响应?
您可以使用 CookieStore,以防他们在 session 期间更新您的 cookie。这将取代将 http cookie 设置为 headers。但会适应任何 Set-Cookie 响应 headers.
https://whosebug.com/a/35346473/1542667
但他们可以并且可能会使用其他信号,例如传入请求率,这些信号看起来不像人类在使用该网站。
但是您正在与一个网站进行猫捉老鼠的游戏,该网站完全不希望您抓取他们的内容。
FWIW 我希望他们赢得这场战斗,在这种情况下你是“坏演员”。无论如何,祝你好运。