我一直在创建一个登录并抓取网站的 Android 应用程序。不幸的是,我一直在使用 JSoup 和持久 session cookie 时遇到问题。
每当我尝试发出 POST 请求时,网站都会提示 session 已过期。我已将问题的原因隔离到 JSESSIONID
cookie(因为在尝试登录时在浏览器上删除它会产生相同的结果)。然而,即使我使用 .cookies()
方法包含所有以前的 cookie,网站仍然会提示 session 已过期。
我想知道我是否犯了任何明显的错误,导致我的应用无法正常维护 session 。
到目前为止我的代码的相关部分(注意:我在这个项目中使用 Kotlin):
val url = "omitted here"
val username = "user"
val password = "hunter2"
val initial = Jsoup.connect(url)
.method(Connection.Method.GET).execute()
val cookies = initial.cookies()
val login = Jsoup.connect(url)
.userAgent("Mozilla")
.data("login_name", username)
.data("password", password)
.cookies(cookies)
.post()
如有任何帮助,我们将不胜感激!
最佳答案
假设 cookie 是由服务器设置的,而不是稍后通过 JavaScript 设置的,那么您的代码看起来是正确的。假设没有丢失代码,cookie 应该进入第二个请求。可能是您误解了网站的工作方式以及它使用 cookie 的方式,也可能是它在登录之前不会分配有效的 cookie,并且总是在任何未登录的 cookie 上提示“ session 已过期”。也许根本不是代码错误,而是逻辑问题。
但是如果您不考虑以下因素,您的完整代码也可能是错误的:
您需要记住,Jsoup 库仅在特定请求从服务器接收到 Set-Cookie
header 时才返回该请求的 cookie。它不返回“所有已知 cookie”的列表。因此,您必须维护一个 map ,该 map 是每个 cookie 响应的持续累积。
将 response.cookies()
方法视为实际上是 response.newCookiesAddedFromThisRequest()
。代码模式是:
val cookies = mutableMapOf<String, String>()
val initialResponse = Jsoup.connect("http://www.whatarecookies.com/cookietest.asp")
.method(Connection.Method.GET)
.cookies(cookies)
.execute()
cookies.putAll(initialResponse.cookies())
val secondResponse = Jsoup.connect("http://www.whatarecookies.com/cookietest.asp")
.method(Connection.Method.GET)
.cookies(cookies)
.execute()
cookies.putAll(secondResponse.cookies())
// `cookies` now contains all cookies added accumulatively
在此代码中,返回的新 cookie 每次都会添加到托管的 cookie 映射中,并且所有 cookie 的总数都会在每次请求时发送。
另请注意:Jsoup 不按 header 顺序处理 cookie,因此有时会为 cookie 设置错误的值。有时它也会意外地将 cookie 值保留为 null。你应该检查 known cookie issues对于 Jsoup。另一种方法是使用类似 OkHttp 的东西进行文档的检索,然后使用 Jsoup 对其进行解析。 Jsoup 不像 HTML 解析和操作那样关注 HTTP 协议(protocol)。
关于android - session cookie 不会与 JSoup 保持一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38818416/