- UID
- 205569
- 在线时间
- 0 小时
- 最后登录
- 2015-6-3
- 注册时间
- 2012-8-25
- 宅魂
- 2820 点
- 贡献
- 299 点
- 宅币
- 17268 枚
- 宅の石(入宅度)
- 0 块
- 元气(技能点)
- 34 点
- 活跃
- 0 ℃
- 听众
- 9
- 收听
- 1
该用户从未签到
技术宅认证程序员
重度中二患者
- 积分
- 28325
|
本帖最后由 foodszhu 于 2012-11-21 00:23 编辑
继续前一篇的内容,姬宅百度贴吧的自动签到菜鸟脚本教程(一)登陆篇
(一)准备
其实经过上一篇所讲,签到也是一个类似的过程
这次我们用firefox的firebug插件为例来探究下签到的过程
1.姬宅签到:
因为自己自从写了这个脚本之后就真的自动签到了。。所以新建了一个号来截图。。不过用户组在loading下无法完成签到,不过仍可以登陆进签到中心,来查看提交的表单,跟在主页签到完全一样。进入页面打开firebug,进入网络分页,点击保持按钮保证处于保持状态,然后选好参数,这里我选择不想填写,签到心情是慵懒。单击开始签到
同登陆时一样,是一个post表单,url是https://www.gn00.com/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&inajax=1,qdmode是签到模式,貌似1是自己填写,3是不想填写,2是什么不清楚,qdxq是签到心情,yl是慵懒。。好吧都是拼音。。
这些都是可以固定下来或者随机选取的。而唯一看似重要的formhash是什么呢?我们打开页面的源代码进行搜索。。
表单处理那发现这么一行[mw_shl_code=html,true]<form id="qiandao" method="post" action="plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1">
<input type="hidden" name="formhash" value="05bdef8b">[/mw_shl_code]
明显为我们所需。。在登陆的基础上,签到明显是个简单活动
2.贴吧签到
以bilibili吧为例
登陆bilibili吧,单击签到,
也是post表单,url为http://tieba.baidu.com/sign/add,三个参数也十分简单
ie估计是编码格式,kw为贴吧名称,tbs估计为贴吧的代码,打开源代码进行搜索
[mw_shl_code=html,true]<script>
PageData.tbs = "483101895300e4521353410592";[/mw_shl_code]
可查到这么一行,说明tbs也可从本页面直接获取。
需要注意的是,中文贴吧名在转化为url时,必须是由gbk码转换成url。才能正常访问
把所需要的数据放在qiaodao.ini中方便读取
[mw_shl_code=text,true]#qiandao.ini
[技术宅]
url=https://www.gn00.com
qiandao_url=https://www.gn00.com/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&sign_as=1&inajax=1
fastreply=0
formhash=
qdmode=3
qdxq=fd
todaysay=
[百度]
url=http://www.baidu.com
qiandao_url=http://tieba.baidu.com/sign/add
ie=utf-8
kw=
tbs=[/mw_shl_code]
不过单纯一个贴吧的签到当然无法满足我们,我们要尝试下签到所有喜欢的贴吧,第一步,就要找出自己的喜爱的贴吧。
这里我提供两种方案
1.通过http://www.baidu.com/p/用户名?from=tieba进入到百度个人主页的我在贴吧子页,从中获取我最喜爱的吧。
2.在登陆状态下,通过http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=用户名进入到个人的i贴吧,从中提取我爱逛的贴吧。
具体操作稍后再讲
相比登陆方面,签到简直是没有任何难度。。。所以我们就要在脚本上下点功夫了
(二)脚本
先上总脚本,这个签到本来是一件非常简单的事,但是不比登陆,我们往往需要获得一些签到返回的信息,所以对返回信息稍作处理
[mw_shl_code=python,true]#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# qiandao.py
import login,re,urllib,urllib2,json,threading
import ConfigParser as cp
class Qiandao(login.Login):
def __init__(self,name):
super(Qiandao,self).__init__(name)
self.loadIni('qiandao.ini',name,self.data,'url','qiandao_url')
def qiandao(self):
data = urllib.urlencode(self.data)
req = urllib2.Request(self.qiandao_url,data,self.headers)
response = self.opener.open(req)
self.qiandao_response=response
self.qiandao_response_read=response.read().decode('utf-8')
return self.qiandao_response_read
class TiebaQiandao(Qiandao,login.BaiduLogin):
def __init__(self,name='百度'):
self.result_list={u'cont_sign_num':u'连续签到天数', u'cout_total_sing_num':u'本月累计签到天数',u'user_sign_rank':u'个人签到排名',u'tieba_name':u'贴吧'}
super(TiebaQiandao,self).__init__(name)
def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t
def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response
def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list
def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[]
for i in j:
l.append(i['name'].encode('utf-8'))
print i['name'].encode('utf-8')
return l
def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result
def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''
class JishuzhaiQiandao(Qiandao,login.JishuzhaiLogin):
def __init__(self,name='技术宅'):
super(JishuzhaiQiandao,self).__init__(name)
def getFormHash(self):
buf=self.opener.open(self.url).read().decode('utf-8')
r=r'formhash=\w+'
s=re.findall(r,buf)[0].split('=')[1]
return s
def qiandao(self):
self.setData(formhash=self.getFormHash())
response = super(JishuzhaiQiandao,self).qiandao()
return response
def analyseQiandaoResult(self):
r=r'<div class="c">\r\n(.*?) </div>'
result=re.findall(r,self.qiandao_response_read)[0]
if u'成功' in result:
no=0
else:
no=1
return no,result
def printQiandaoResult(self):
no,result=self.analyseQiandaoResult()
print '技术宅社区:'
if no == 0:
print '签到成功:'
else:
print '签到失败:'
print result
print ''
def main(name):
if name=='技术宅':
website=JishuzhaiQiandao()
website.login()
website.qiandao()
website.printQiandaoResult()
elif name=='百度':
tieba_name=raw_input("输入您想签到的贴吧名称(如果想签到所有喜欢贴吧请打all):").lower()
website=TiebaQiandao()
website.login()
if tieba_name != 'all':
website.printQiandaoResult(*website.analyseQiandaoResult(*website.qiandao(tieba_name)))
else:
response_list=website.qiandaoAll()
for item in response_list:
website.printQiandaoResult(*website.analyseQiandaoResult(*item))
else:
print '没有填写配置文件!'
return 1
return 0
if __name__ == '__main__':
name=raw_input('输入您想登陆的网站名称(确保您已填写配置文件):')
main(name)
[/mw_shl_code]
[mw_shl_code=python,true]import login,re,urllib,urllib2,json
import ConfigParser as cp[/mw_shl_code]
依旧是首先引入模块,这里需要引入上篇我们写的登陆模块。。
[mw_shl_code=python,true]class Qiandao(login.Login):
def __init__(self,name):
super(Qiandao,self).__init__(name)
self.loadIni('qiandao.ini',name,self.data,'url','qiandao_url')
def qiandao(self):
data = urllib.urlencode(self.data)
req = urllib2.Request(self.qiandao_url,data,self.headers)
response = self.opener.open(req)
self.qiandao_response=response
self.qiandao_response_read=response.read().decode('utf-8')
return self.qiandao_response_read[/mw_shl_code]
同样是先构造签到的基类,由于签到是基于登陆完成,且两者有很多共同之处,所以将Login类设为Qiandao类的基类,可以省下很多操作
初始化时多一步读取qiandao.ini的内容作为表单值。
定义新的方法qiandao作为签到的实际做法,不过跟登陆的做法极为类似,只是换掉了登陆的url而已,不过这个qiandao必须在已登陆的前提下再进行签到。
[mw_shl_code=python,true]class TiebaQiandao(Qiandao,login.BaiduLogin):
def __init__(self,name='百度'):
self.result_list={u'cont_sign_num':u'连续签到天数', u'cout_total_sing_num':u'本月累计签到天数',u'user_sign_rank':u'个人签到排名',u'tieba_name':u'贴吧'}
super(TiebaQiandao,self).__init__(name)
def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t
def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response
def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list
def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[]
for i in j:
l.append(i['name'].encode('utf-8'))
print i['name'].encode('utf-8')
return l
def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result
def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''
[/mw_shl_code]
当签到的基类构造好时我们就要构造下一步的子类了,但是在登陆基类我们已经派生出两个子类BaiduLogin和JishuzhaiLogin,来分别处理百度与姬宅的登陆,所以我们既需要从登陆的两个子类中继承需要的功能,又需要从签到基类中继承所需要的功能,所以我们采用多继承的方法。
在我们的TiebaQiandao类中,我们既继承了BaiduLogin类,又继承了Qiandao类,为了防止共同父类方法的多次调用,我们采用super来调用父类的方法。
super是采用mro方式处理多继承中共同方法的多次调用的问题的,所以为了运行良好,我们必须将所有的调用父类的形式都改为super
同时,由于新型类中,mro顺序是广度优先的,所以同层间的相同方法最好使用相同的参数个数,否则就可能报错,而且达不到我们想要的结果。关于这部分的讨论,搜索一下python的多继承
[mw_shl_code=python,true]def getTiebaKw(self,name):
return urllib2.quote(name.decode('utf-8').encode('gbk'))
def getTiebaTbs(self,name):
url='http://tieba.baidu.com/f?kw='+self.getTiebaKw(name)
buf=self.opener.open(url).read()
s=r'PageData.tbs = \"(\w+)\"'
t=re.findall(s,buf)[0]
return t[/mw_shl_code]
这两个函数是为了得到签到的表单项之一的tbs,我们从该贴吧的页面中获取信息,所以得先进入这个贴吧,
而贴吧url形式为http://tieba.baidu.com/f?kw=贴吧名,当然贴吧名需要处理为url能识别的形式,而且得从gbk码转换而来,由于我编码的统一为utf-8,所以要做进一步转换
同样用正则表达式将tbs挑捡出来
[mw_shl_code=python,true]def getAllTiebaList(self):
#url='http://www.baidu.com/p/%s?from=tieba' % self.getTiebaKw(self.data['username'])
#r=r'target=_blank title=\\x22(.*?)\\x22'
#for i,v in enumerate(l):
# l=v.rstrip('\xe5\x90\xa7')
#return l
url='http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=%s' % self.getTiebaKw(self.data['username'])
r=r'\$_likeForum=(.*?);'
buf=self.opener.open(url).read()
l=re.findall(r,buf)[0]
j=json.loads(l)
l=[i['name'].encode('utf-8') for i in j]
return l[/mw_shl_code]
getAllTiebaList是获取喜爱贴吧的方法,其中我注释的部分是我在准备篇中所说的第一种方法,即进入到个人主页中提取。。其中包含在target=_blank title=后面的即是贴吧名,不过后面多了一个吧字,在这里我们用rstrip将其消掉,字符串rstrip方法用于消去共同后缀,rstrip消去共同前缀,使用默认参数时消去空格
第二种方法,即在登陆前提下,进入个人的i贴吧,从中获取贴吧信息,而这个部分信息较为混杂,我们仔细查看,发现在响应的末尾有一组以脚本形式存储的信息,以$_likeForum开头的数据
我们先用re模块将字符串提取出来,注意$需要转义所以加\,然后用json模块将字串转化为我们能够直接用的对象,在这里面会生成一组列表,列表中每一项都是一个字典,包括了爱逛的贴吧的信息,这里我们暂且只用name这一对键值,同时用了列表推导的技巧生成了这个列表
[mw_shl_code=python,true]def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response[/mw_shl_code]
qiandao方法是对父类的签到方法的具体实现,对于贴吧签到而言,我们不仅需要登陆百度,而且还需要知道所要签到的贴吧名,在加上贴吧的tbs后,发送表单完成签到
同时返回贴吧名与响应的元组
[mw_shl_code=python,true]def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result[u'tieba_name']=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result[/mw_shl_code]
analyseQiandaoResult方法正是为了分析qiandao方法返回响应的方法,它所需参数正好是签到返回的结果,而这个响应结果,直接是以json形式存储的,所以我们可以用json模块直接提取出来,其中no是返回代码,0即登陆成功,1101代表已经登陆,1007代表今天签到次数超过100次,error即错误说明。
如果签到成功,响应中data对应值即是一些个人排名啊,贴吧排名,贴吧目录等项,uinfo代表个人信息,我们这里只取个人信息保存。最终返回响应代码与一个打包好的字典作为返回结果
[mw_shl_code=python,true]def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result[key])
else:
print "贴吧 : %s" %result[0]
print '签到失败 : %s'%result[1].encode('utf-8')
print ''[/mw_shl_code]
从分析结果中我们最终打印出我们需要的结果。。这块就不多说了。
[mw_shl_code=python,true]def qiandaoAll(self,*except_list):
self.qiandao_response_list=[self.qiandao(item) for item in self.getAllTiebaList() if item not in except_list]
return self.qiandao_response_list[/mw_shl_code]
qiandaoAll方法用于签到所有爱逛的贴吧,参数中except_list用于设定无需签到的贴吧,这里其实可以用多线程,不过仔细想想还是觉得略麻烦而且在gae上部署也很麻烦多以就放弃了
姬宅的签到与贴吧签到类似,只需要加上一个formhash即可提交。当然两者都需要先login,再qiandao
最后我们就可以来个一键签到了
[mw_shl_code=python,true]#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# 一键签到.py
#
import qiandao,os
def main():
jishuzhai=qiandao.JishuzhaiQiandao()
baidu=qiandao.TiebaQiandao()
jishuzhai.login()
baidu.login()
jishuzhai.qiandao()
jishuzhai.printQiandaoResult()
response_list=baidu.qiandaoAll()
for item in response_list:
baidu.printQiandaoResult(*baidu.analyseQiandaoResult(*item))
return 0
if __name__ == '__main__':
main()[/mw_shl_code]
将这个代码文件设为可执行,需要签到时运行即可
自动签到的主体部分就到此结束了。。。
下来一篇就是将如何将这个脚本部署在gae上,并且用计划任务在12点附近进行签到。。。不过gae要求只能有最多30s的响应时间所以12点刚过那阵贴吧签到各种Deadline exceeded。。。。几乎到快到20才能勉强签上。。不知为何。。暂时也没有用多线程。。难道只有用多线程才能改进一下么
恩恩。。下一篇就是部署到gae上,并进行少量优化
发帖果然理会的人不多啊。。。而且自己话也说不太清楚。。。自己第一次写教程也请各位见谅。。
再。。求发糖
|
评分
-
参与人数 6 | 宅魂 +13 |
宅币 +80 |
贡献 +4 |
元气(技能点) +4 |
收起
理由
|
因果律
| + 1 |
+ 3 |
|
|
Σ( ° △ °|||)︴ 碉堡了 |
打破沙锅
| |
+ 2 |
|
|
o(* ̄▽ ̄*)ブ 发糖 |
斜渡_桃之夭夭
| + 2 |
+ 5 |
|
|
o(* ̄▽ ̄*)ブ 发糖 |
苏Xx摩ヤ
| + 10 |
+ 50 |
|
|
Σ( ° △ °|||)︴ 碉堡了 |
风音洛洛
| |
+ 20 |
+ 4 |
|
o(* ̄▽ ̄*)ブ 发糖 |
Nekor
| |
|
|
+ 4 |
o(* ̄▽ ̄*)ブ 发糖 |
查看全部评分
|