Scala爬虫分页获取数据失败,请求返回302跳转至登录页
解决Scala爬虫分页请求跳转问题
问题背景
使用Scala 2.13.1 + net.ruippeixotog%%scala-scraper%3.0.0的JsoupBrowser爬取目标网站:
- 成功从首页GET请求获取
__RequestVerificationToken,携带该Token发送POST请求可拿到第一页数据 - 分页请求未携带Token时返回登录表单;改用Akka HTTP实现后,返回302跳转至登录页,仍无法获取分页数据
现有代码片段
首页获取Token(正常工作)
val browser = JsoupBrowser() val homepageDoc = browser.get("example.com") val requestVerificationToken = homepageDoc >> element("input[name='__RequestVerificationToken']") >> attr("value")
第一页请求(正常工作)
val formData = Map( "searchtype" -> "C", "__RequestVerificationToken" -> requestVerificationToken ) val doc = browser.post(url, formData)
分页请求(失败)
val nextPageFormData = Map( "undefined" -> "", "sortby" -> "", "stype" -> "a", "pidx" -> "2" ) val doc = browser.post(url, nextPageFormData)
Akka HTTP尝试(返回302)
implicit val actorSystem: ActorSystem = ActorSystem() implicit val executionContext: ExecutionContextExecutor = actorSystem.dispatcher val browser = JsoupBrowser() val homepageDoc = browser.get("example.com") val requestVerificationToken = homepageDoc >> element("input[name='__RequestVerificationToken']") >> attr("value") val url = "searchpage.com" val postBody = "undefined=&sortby=&stype=a&pidx=2" val request = HttpRequest(HttpMethods.POST, url, Seq(RawHeader("__requestverificationtoken",requestVerificationToken)), HttpEntity(ContentTypes.`application/x-www-form-urlencoded`, postBody)) val responseFuture = Http(actorSystem).singleRequest(request) responseFuture .onComplete { case Success(res) => println(res) Unmarshal(res.entity.toStrict(5 seconds)).value.map { result => val htmlStr = result.data.utf8String val browser = JsoupBrowser() val doc = browser.parseString(htmlStr) println(doc) } case Failure(e) => println(e) }
核心问题分析
- 会话一致性丢失:JsoupBrowser默认维护Cookie会话,但分页请求若使用新实例或Cookie未正确携带,后端会判定为未授权
- 验证Token未正确传递:部分网站分页请求仍需携带
__RequestVerificationToken,即使前端表单看似没有要求 - Akka HTTP未处理Cookie与跳转:Akka HTTP默认不自动管理Cookie,也不会自动跟进302跳转,导致会话中断
解决方案
方案1:修复scala-scraper分页请求
- 复用同一个
JsoupBrowser实例,确保Cookie会话延续 - 分页请求强制携带
__RequestVerificationToken - 可打印
browser.cookies确认Cookie是否正常携带
修正后的分页代码:
// 复用初始化好的browser实例,不要新建 val nextPageFormData = Map( "undefined" -> "", "sortby" -> "", "stype" -> "a", "pidx" -> "2", "__RequestVerificationToken" -> requestVerificationToken // 强制添加Token ) val doc = browser.post(url, nextPageFormData)
方案2:修复Akka HTTP请求
- 从首页请求中提取Cookie,在后续请求中携带
- 配置Akka HTTP自动跟进302跳转
- 确保Token放在Form数据中(部分网站仅识别Form中的Token,而非Header)
修正后的Akka HTTP代码:
implicit val actorSystem: ActorSystem = ActorSystem() implicit val executionContext: ExecutionContextExecutor = actorSystem.dispatcher implicit val timeout: Timeout = 10 seconds // 第一步:获取首页Cookie和Token val homepageRequest = HttpRequest(HttpMethods.GET, "example.com") val homepageResponseFuture = Http(actorSystem).singleRequest(homepageRequest) homepageResponseFuture.flatMap { homepageRes => // 提取Cookie val cookies = homepageRes.headers.collect { case `Set-Cookie`(cookieStr) => cookieStr.split(";").head // 提取核心Cookie键值对 }.mkString("; ") // 解析首页HTML获取Token Unmarshal(homepageRes.entity.toStrict(5 seconds)).to[String].map { html => val doc = JsoupBrowser().parseString(html) doc >> element("input[name='__RequestVerificationToken']") >> attr("value") }.flatMap { token => // 构造分页请求,携带Cookie和Token(放在Form中) val postBody = s"undefined=&sortby=&stype=a&pidx=2&__RequestVerificationToken=$token" val pageRequest = HttpRequest( HttpMethods.POST, "searchpage.com", Seq( RawHeader("Cookie", cookies), RawHeader("Content-Type", "application/x-www-form-urlencoded") ), HttpEntity(ContentTypes.`application/x-www-form-urlencoded`, postBody) ) // 使用Akka HTTP的superPool自动跟进302跳转 Http(actorSystem).superPool[Unit]().ask((pageRequest, ())) .map(_._1) .flatMap { res => Unmarshal(res.entity.toStrict(5 seconds)).to[String].map { html => val resultDoc = JsoupBrowser().parseString(html) // 处理结果文档 println(resultDoc) } } } }.recover { case e => println(s"请求失败: ${e.getMessage}") }
额外排查点
- 查看浏览器DevTools中的分页请求细节:确认实际请求是否携带Cookie、Token,以及请求头/Form数据的完整内容
- 部分网站会检查
Referer头,可在请求中添加Referer为首页URL - 若Token有有效期,分页请求需确保使用的Token未过期,必要时重新从首页获取
内容的提问来源于stack exchange,提问作者Zaryab Ali
相关产品推荐
相关产品推荐

