Python中如何使用pylogin搞定百度统计

概述

这次分析的百度统计登录接口,算是这几个中最简单的了。

但是学到了一个新东西,叫做 js 模板,搞 web 的同学应该知道,我这种 web 半吊子第一次见,非常有意思。

工具:

1. chrome/firefox
2. f12,network
3. python:requests、re

登录接口

打开百度统计首页https://tongji.baidu.com/web/welcome/login,点开登录框,f12。尝试输入之后,查看发送的数据。

Request URL:https://cas.baidu.com/?action=login
Request Method:POST
Status Code:200 OK

appscope[]:6 appscope[]:7 appscope[]:12 appid:12 entered_login:anhkgg //名字 entered_password:1111111111111111 //密码 entered_imagecode:9mxm //验证码 charset:utf-8 fromu:https://tongji.baidu.com/web/welcome/loginback selfu:https://tongji.baidu.com/web/welcome/login senderr:1

除了上面注释的需要输入的三个字段,其他字段意义都不明确,偷点懒,多次尝试后发现其他字段不会变化,那么就用固定值了。

点击验证码,看到网络,拿到获取验证码的请求,key 使用 10 位时间戳。

GET https://cas.baidu.com/?action=image&key=1503151305

所以登录接口就出来了,vcode需要人工输入。

url = 'https://cas.baidu.com/?action=image&key=' + time_stamp(10)
r = self.s.get(url)

payload = { ‘appscope[]’:6, ‘appscope[]’:7, ‘appscope[]’:12, ‘appid’:12, ‘entered_login’:name, ‘entered_password’:pwd, ‘entered_imagecode’:vcode, ‘charset’:‘utf-8’, ‘fromu’:‘https://tongji.baidu.com/web/welcome/loginback’, ‘selfu’:‘https://tongji.baidu.com/web/welcome/login’, ‘senderr’:1, }
url = ‘https://cas.baidu.com/?action=login’ r = self.s.post(url, data = payload)

接着看看登录返回状态,如果失败了,返回数据中包含如下数据:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="ReFresh" content="0; url=https://tongji.baidu.com/web/welcome/login?fromu=https%3A%2F%2Ftongji.baidu.com%2Fweb%2Fwelcome%2Floginback&e=%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%E9%94%99%E8%AF%AF&un=anhkgg&aid=12&errno=132" />
<title>正在处理...</title>
</head>
<body>
    <script>                
    var url="https://tongji.baidu.com/web/welcome/login?fromu=https%3A%2F%2Ftongji.baidu.com%2Fweb%2Fwelcome%2Floginback&e=%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%E9%94%99%E8%AF%AF&un=anhkgg&aid=12&errno=132";
    location.href=url;
    </script>

</body> </html>

然后浏览器加载该 url,显示错误提示信息

Request URL:https://tongji.baidu.com/web/welcome/login?fromu=https%3A%2F%2Ftongji.baidu.com%2Fweb%2Fwelcome%2Floginback&e=%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%E9%94%99%E8%AF%AF&un=anhkgg&aid=12&errno=132
Request Method:GET

fromu:https://tongji.baidu.com/web/welcome/loginback e:用户名密码错误 un:anhkgg aid:12 errno:132

其中e是错误提示信息,errno 是错误号。

登录成功返回数据如下,没有e错误信息。

<script>                
var url="http://cas.baidu.com/?action=check&appid=12&u=https%3A%2F%2Ftongji.baidu.com%2Fweb%2Fwelcome%2Floginback%3Fcastk%3Dc4086gh7e82166251d451&fromLogin=1";
location.href=url;
</script>

那么就可以先通过正则拿到 url,通过搜索 url 是否有e判断是否登录成功,并且拿到提示信息。成功则继续访问该 url 跳转到成功页面,获取其他需要的信息。

pattern = re.compile(r'var url="(.*?)";')
cont = re.search(pattern, r.content)
url = cont.group(1)
pattern = re.compile(r'e=(.*?)&un=')
cont = re.search(pattern, url)
if cont != None:
    r = urllib.unquote(cont.group(1)) #失败
    return utf2gbk(r)        

r = self.s.get(url) # 成功

js 模板

这里比较意思的是使用的 js 模板来生成登录表单。

具体 js 模板使用看这里

<script id="LoginTemplate" type="text/template">
&lt;div id="LoginContainer" class="login-dialog"&gt;
    &lt;div id="TopTmp"&gt;&amp;nbsp;&lt;/div&gt;

    if (this.isIco == 1) {
    &lt;div id="LoginMain" class="ico-login clearfix"&gt;
        &lt;div class="visitor-login-tab" id="LoginTab"&gt;请输入查看密码&lt;/div&gt;
        &lt;div id="LoginInput" class="login-input"&gt;
            if (this.errMsg) {
            &lt;div id="ErrorTip" class="error"&gt;#{this.errMsg}&lt;/div&gt;
            }
            ...
        &lt;/div&gt;
    &lt;/div&gt;
    }
    else {
    &lt;div id="LoginMain" class="login-main"&gt;
        
            &lt;form method="post" action="#{this.loginAction}"&gt;
                &lt;input type="hidden" value="12" id="Appid" name="appid"&gt;
                ...
                &lt;input type="hidden" value="#{this.selfUrl}" name="selfu" /&gt;
                &lt;input type="hidden" value="1" name="senderr" /&gt;
            &lt;/form&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    }
&lt;/div&gt;
&lt;div class="dialog-bottom-bg"&gt;&lt;/div&gt;

</script>

从上面代码中可以看到,某些标签的值使用了#{this.xxx}这样的语法,不是直接填入的具体内容,更加灵活,扩展更容易。

然后在点击登录按钮之后,通过函数格式化一个全局定义的变量来生成的登录表单。具体如下:

//全局数据,用于替换表单中的 this.xxx
<script type="text/javascript">
VAR = {
    webMasterRegister: "https://tongji.baidu.com/web/register",
    customRegister: "https://u.baidu.com/ucweb/?module=Reguser&controller=reg&action=index&appid=3",
    union_forget: "http://union.baidu.com/findPassword!input.action",
    shifen_forget: "https://aq.baidu.com/new/#/findpwd",
    uc_forget: "https://aq.baidu.com/new/#/findpwd",
    waiting_img_src: "/web/img/loadingImage.gif",
    app_id: "0",
    errMsg: "",
    loginUrl: "/web/welcome/login",
    loginAction: "https://cas.baidu.com/?action=login",
    userName: "",
    authCode: "https://cas.baidu.com/?action=image&key=1503151305",
    registerUrl: "/web/register",
    fromUrl: "https://tongji.baidu.com/web/welcome/loginback",
    selfUrl: "https://tongji.baidu.com/web/welcome/login",
    isIco: "0",
    webmasterUserNum: "2097176",
    customerUserNum: "2270927",
    mtjUserNum: "2262130"
};
</script>

然后在 login.js 中,通过下面的函数来初始化表单,并且显示。

其中n.format("LoginTemplate", VAR)用于格式化 VAR 定义的数据到表单的数据中。

, h = function() {
    var e = t(".login-trigger").eq(0);
    e.on("click", function() {
        s || (s = new i({
            width: 345,
            isModal: !0,
            titleText: "",
            isSingle: !0,
            content: n.format("LoginTemplate", VAR) //初始化登录表单数据
        }),
        loginController.init()),
        s.show()
    });

而在 format 具体如何替换的,就随意实现了,这里就不在具体分析,有兴趣跟着分析的同学可以去看看 common.js 中的代码。

总结

百度统计接口非常简单,密码未做变换,使用 https。

登录之后具体做什么也不在分析。

预告下次做百度主站的登录分析,简单看了下,非常...复杂!

博客原文:https://anhkgg.github.io/pylogin-baidutongji-login-analyze/


Python中如何使用pylogin搞定百度统计

2 回复

我无法理解你的问题


楼主 666,实践才能巩固学习

回到顶部