最近在学习 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 ,问题出在哪里呢? 代码写的不是很好,大家轻拍。。
自己重新用火狐分析了下登录、签到的相关报文,发现最后请求http://www.v2ex.com/mission/daily/redeem?once=xxx时比正常浏览器请求少了一个 cookie:V2EX_TAB
,后面排查了一下,发现这个cookie是在登录成功后,跳转到首页时set进去的,而我上面的代码,在登录成功收到httpcode 302后,就直接进行签到的操作了,没有跳转首页,所以少了这个cookie。
重新修改代码,登录后跳转一次首页获取V2EX_TAB
这个cookie,再继续后面操作,就能正常签到了。
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' |
2
mx1700 2016-07-05 08:05:19 +08:00 via Android 1
领取每日奖励的请求本来就是个 302 跳转吧
|