想用elisp改写一个 V2EX 自动签到脚本,为什么会无法登录v2ex呢?

诸位, V2EX 自动签到脚本崩了,你们发现了吗? 中有一个python实现的V2EX 自动签到脚本.代码如下

# coding:utf-8

import re
import requests

session = requests.Session()

# 领取 X 铜币
# 每日登录奖励已领取

base_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.71 Safari/537.36 OPR/35.0.2066.23 (Edition beta)', 'Referer': 'http://v2ex.com/signin'}

session.headers = base_headers

resp = session.get('http://v2ex.com/signin')
u, p = re.findall(r'class="sl" name="([0-9A-Za-z]{64})"', resp.text)
once_code = re.search(r'value="(\d+)" name="once"', resp.text).group(1)

resp = session.post('http://v2ex.com/signin', {u:'username', p:'password', 'once':once_code, 'next':'/'})
resp = session.get('http://v2ex.com/mission/daily')

if u'每日登录奖励已领取' in resp.text:
    print('Already got it.')
else:
    resp = session.get('http://v2ex.com' + re.search(r'/mission/daily/redeem\?once=\d+', resp.text).group())
    print(resp.ok)

我想把它改写成elisp

(require 'request)

(defconst v2ex-signin/base-heads '(("User-Agent" . "Mozilla/5.0 (Windows NT 10.0 ; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.71 Safari/537.36 OPR/35.0.2066.23 (Edition beta)") ("Referer" . "http://v2ex.com/signin")))


(defun v2ex-signin/parse-signin ()
  "解析sigin网页,返回用户,密码的键与once_code的值"
  (let (u p once-code)
    (search-forward-regexp "class=\"sl\" name=\"\\([[:alnum:]]\\{64\\}\\)\"")
    (setq u (match-string-no-properties 1))
    (search-forward-regexp "class=\"sl\" name=\"\\([[:alnum:]]\\{64\\}\\)\"")
    (setq p (match-string-no-properties 1))
    (search-forward-regexp "value=\"\\([[:digit:]]+\\)\" name=\"once\"")
    (setq once-code (match-string-no-properties 1))
    (list u p once-code)))

(defun v2ex-signin/signin (u p once-code)
  "v2ex签到"
  (request "http://v2ex.com/signin"   ;; 这一个request应该能登录,但是实际却失败了,为什么??
           ;; :type "POST"
           :data `((,u . "username")  ;;改成实际用户名
                   (,p . "password")    ;; 改成实际密码
                   ("once" . ,once-code)
                   ("next". "/"))
           :complete (cl-function (lambda (&key data &allow-other-keys)
                                    (request "http://v2ex.com/mission/daily"
                                             :headers `(("Cookie" . ,(request-cookie-string "v2ex.com" "/")))
                                             :parser (lambda ()
                                                       (decode-coding-string (buffer-string) 'utf-8))
                                             :success (cl-function
                                                       (lambda (&key data &allow-other-keys)
                                                         (message "daily get: %S" data))))))))

(defun v2ex-signin/parse-daily ()
  "解析出v2ex日常任务的访问地址"
  (search-forward-regexp "/mission/daily/redeem\\?once=[0-9]+")
  (concat "http://v2ex.com" (match-string-no-properties 0)))

;; 尝试登录,并获取每日任务
(request "http://v2ex.com/signin"
         :parser 'v2ex-signin/parse-signin
         :complete  (cl-function
                     (lambda (&key data &allow-other-keys)
                       (apply 'v2ex-signin/signin data))))

;; (request-cookie-string "v2ex.com" "/")

;; if u'每日登录奖励已领取' in resp.text:
;; print('Already got it.')
;; else:
;; resp = session.get('http://v2ex.com' + re.search(r'/mission/daily/redeem\?once=\d+', resp.text).group())
;; print(resp.ok)

但是发现改写后的脚本,无法登录. 请问是错在哪里了呢?

我不喜欢这个问题的问法,“无法登录 V2EX “只是最终的结果,作为问题本身显得 OP 有些偷懒 :disappointed:

你贴出的 Python 程序中大致有三个步骤:

  1. 获取 once_code
  2. 签到
  3. 查询签到的结果

每一步对应着一个请求,在你用 Elisp 改写后,哪些步能工作,那些不能?在出问题的地方,实际的结果是什么?而你预期的又结果是什么?

1 个赞

Sorry, 我以为在注释里面已经说的足够清楚了.

如你所说,整个程序的第一步是获取once_code的值以及登录时的用户和密码标签的name

第二个步骤是用第一步取得的信息模拟登录的http请求. 这一步本应该是返回一个登录成功的界面,但是实际上却登录失败了. 这一步在elisp的源代码中对应的是 ‘v2ex-signin/signin’ 函数中的第一个request函数请求

(defun v2ex-signin/signin (u p once-code)
  "v2ex签到"
  (request "http://v2ex.com/signin"   ;; 这一个request应该能登录,但是实际却失败了,为什么??

而我想问的就是,这一步为什么会登录失败

可能有UserAgent的问题。可以抓包,用curl手动模拟一下。

抓包…不太会~~,求分解动作

wireshark?

1 个赞