V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
caixiexin
V2EX  ›  问与答

用 scala 写了一个 v 站的签到脚本,但是最后总是 302,大家帮我分析分析?

  •  
  •   caixiexin · 2016-07-04 21:55:49 +08:00 · 2401 次点击
    这是一个创建于 3062 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在学习 scala ,用 v 站签到来练练手。 这个签到脚本主要是参考 https://github.com/lqccan/v2ex-sign/blob/master/v2ex.py 这位 v 友写的签到脚本,自己用 scala 实现了一下,登录是没问题的,但是到最后一步 /mission/daily/redeem?once=xxx 时却失败了,返回 302 ,跳转回 /mission/daily 页面。 以下是代码:

    import java.net.HttpCookie
    
    
    
    import scalaj.http.{Http, HttpResponse}
    
    
    object V2Sigin2 {
    
      def main(args: Array[String]): Unit = {
        val signPage: HttpResponse[String] = Http("http://www.v2ex.com/signin").asString
        val html = signPage.body
    
        val cookieMap: scala.collection.mutable.Map[String, HttpCookie] = scala.collection.mutable.Map[String, HttpCookie]()
        signPage.cookies.foreach(f => cookieMap.put(f.getName, f))
    
    
        val nameMatch = "type=\"text\" class=\"sl\" name=\"([a-f0-9]{64,64})\"".r findFirstMatchIn html
        val pwdMatch = "type=\"password\" class=\"sl\" name=\"([a-f0-9]{64,64})\"".r findFirstMatchIn html
        val onceMatch = "value=\"(\\d+)\" name=\"once\"".r findFirstMatchIn html
        val nameName = if (nameMatch.isEmpty) "" else nameMatch.get.group(1)
        val pwdName = if (pwdMatch.isEmpty) "" else pwdMatch.get.group(1)
        val once = if (onceMatch.isEmpty) "" else onceMatch.get.group(1)
        val next = "/"
        val loginResult = Http("http://www.v2ex.com/signin").postForm(
          Seq(nameName -> "username",
            pwdName -> "password",
            "once" -> once,
            "next" -> next
          )
        ).headers(Seq("Referer" -> "http://www.v2ex.com/signin",
          "User-Agent" -> "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"
        ))
          //      .cookies(signPage.cookies)
          .cookies(cookieMap.values.toSeq)
          .asString
        loginResult.cookies.foreach(f => cookieMap.put(f.getName, f))
    
    
        if (loginResult.code == 302) {
          val dailyResult = Http("http://www.v2ex.com/mission/daily")
            //      .cookies(loginResult.cookies)
            .cookies(cookieMap.values.toSeq)
            .asString
          dailyResult.cookies.foreach(f => cookieMap.put(f.getName, f))
          if (dailyResult.code != 200) {
            println("没有登录无法签到!")
            return
          }
          if (dailyResult.body.indexOf("fa-ok-sign") > -1) {
            println("本日已签到!")
          } else {
    
            val dailyMatch = "(/mission/daily/redeem\\?once=\\d+)".r findFirstMatchIn dailyResult.body
            val daily = if (dailyMatch.isEmpty) "" else dailyMatch.get.group(1)
            val signResult = Http("http://www.v2ex.com" + daily)
              .cookies(cookieMap.values.toSeq)
              //          .cookies(loginResult.cookies)
              //          .cookies(dailyResult.cookies)
              .headers(
              Seq("Referer" -> "http://www.v2ex.com/mission/daily",
                "User-Agent" -> "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0",
                "Host" -> "www.v2ex.com",
                "Connection" -> "keep-alive"
              )
            ).asString
            println(signResult.code)
            signResult.cookies.foreach(f => cookieMap.put(f.getName, f))
            println("签到成功!")
    
          }
        } else {
          println("登录失败!")
    
        }
        println("============")
        println(cookieMap)
    
    
      }
    
    }
    
    

    一开始以为是 cookie 问题,因为那位 v 友用的 python 的 requests.Session()是能自动管理 cookie 的,而我用的 http 包没有管理上下文的功能,但是不管我怎么设置 cookie ,最终都是返回 302 ,问题出在哪里呢? 代码写的不是很好,大家轻拍。。

    第 1 条附言  ·  2016-07-05 09:38:17 +08:00
    最后 302 重定向到 /mission/daily 页面,页面提示信息是
    “你的浏览器有一些奇奇怪怪的设置,请用一个干净安装的浏览器重试一下吧”
    这种会是“ User-Agent ” 设置的问题吗?
    第 2 条附言  ·  2016-07-06 22:20:32 +08:00

    自己重新用火狐分析了下登录、签到的相关报文,发现最后请求http://www.v2ex.com/mission/daily/redeem?once=xxx时比正常浏览器请求少了一个 cookie:V2EX_TAB,后面排查了一下,发现这个cookie是在登录成功后,跳转到首页时set进去的,而我上面的代码,在登录成功收到httpcode 302后,就直接进行签到的操作了,没有跳转首页,所以少了这个cookie。 重新修改代码,登录后跳转一次首页获取V2EX_TAB这个cookie,再继续后面操作,就能正常签到了。

    3 条回复    2016-07-05 08:44:58 +08:00
    hicdn
        1
    hicdn  
       2016-07-04 22:33:56 +08:00   ❤️ 1
    #!/bin/sh

    cookie=''

    UA=''

    url=$( curl 'https://v2ex.com/mission/daily' -A "$UA" -H 'pragma: no-cache' -H 'dnt: 1' -H 'accept-language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4' -H 'upgrade-insecure-requests: 1' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'cache-control: no-cache' -H "cookie: $cookie" -H 'referer: https://v2ex.com/' | fgrep 'location.href ' | awk -F"'" '{print $(NF-1)}')

    curl "https://v2ex.com$url" --referer "https://v2ex.com/mission/daily" -H "cookie: $cookie" -A "$UA" -H 'pragma: no-cache' -H 'dnt: 1' -H 'accept-encoding: gzip, deflate, sdch' -H 'accept-language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4' -H 'upgrade-insecure-requests: 1' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'cache-control: no-cache'
    mx1700
        2
    mx1700  
       2016-07-05 08:05:19 +08:00 via Android   ❤️ 1
    领取每日奖励的请求本来就是个 302 跳转吧
    caixiexin
        3
    caixiexin  
    OP
       2016-07-05 08:44:58 +08:00 via Android
    @mx1700 恩,不过 302 之后并没有领取成功
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2765 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 13:47 · PVG 21:47 · LAX 05:47 · JFK 08:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.