姬宅百度贴吧的自动签到菜鸟脚本教程(二)签到篇
本帖最后由 foodszhu 于 2012-11-21 00:23 编辑继续前一篇的内容,姬宅百度贴吧的自动签到菜鸟脚本教程(一)登陆篇
(一)准备
其实经过上一篇所讲,签到也是一个类似的过程
这次我们用firefox的firebug插件为例来探究下签到的过程
1.姬宅签到:
因为自己自从写了这个脚本之后就真的自动签到了。。所以新建了一个号来截图。。不过用户组在loading下无法完成签到,不过仍可以登陆进签到中心,来查看提交的表单,跟在主页签到完全一样。进入页面打开firebug,进入网络分页,点击保持按钮保证处于保持状态,然后选好参数,这里我选择不想填写,签到心情是慵懒。单击开始签到
http://m1.img.papaapp.com/farm4/2012/1120/19/45315DD82CC332FFDED47D2C47548A5DB328876E18EF4_443_330.PNG
同登陆时一样,是一个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是什么呢?我们打开页面的源代码进行搜索。。
表单处理那发现这么一行<form id="qiandao" method="post" action="plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1">
<input type="hidden" name="formhash" value="05bdef8b">
明显为我们所需。。在登陆的基础上,签到明显是个简单活动
2.贴吧签到
以bilibili吧为例
登陆bilibili吧,单击签到,
http://m2.img.papaapp.com/farm4/2012/1120/19/5301CFE7B6715F14D7CAC077597617CA854821D6E5AFC_500_151.jpg
也是post表单,url为http://tieba.baidu.com/sign/add,三个参数也十分简单
ie估计是编码格式,kw为贴吧名称,tbs估计为贴吧的代码,打开源代码进行搜索
<script>
PageData.tbs = "483101895300e4521353410592";
可查到这么一行,说明tbs也可从本页面直接获取。
需要注意的是,中文贴吧名在转化为url时,必须是由gbk码转换成url。才能正常访问
把所需要的数据放在qiaodao.ini中方便读取
#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=
不过单纯一个贴吧的签到当然无法满足我们,我们要尝试下签到所有喜欢的贴吧,第一步,就要找出自己的喜爱的贴吧。
这里我提供两种方案
1.通过http://www.baidu.com/p/用户名?from=tieba进入到百度个人主页的我在贴吧子页,从中获取我最喜爱的吧。
2.在登陆状态下,通过http://tieba.baidu.com/i/sys/enter?ie=utf-8&kw=用户名进入到个人的i贴吧,从中提取我爱逛的贴吧。
具体操作稍后再讲
相比登陆方面,签到简直是没有任何难度。。。所以我们就要在脚本上下点功夫了
(二)脚本
先上总脚本,这个签到本来是一件非常简单的事,但是不比登陆,我们往往需要获得一些签到返回的信息,所以对返回信息稍作处理
#!/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)
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=
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)
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=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)
else:
print "贴吧 : %s" %result
print '签到失败 : %s'%result.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).split('=')
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)
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)
import login,re,urllib,urllib2,json
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
同样是先构造签到的基类,由于签到是基于登陆完成,且两者有很多共同之处,所以将Login类设为Qiandao类的基类,可以省下很多操作
初始化时多一步读取qiandao.ini的内容作为表单值。
定义新的方法qiandao作为签到的实际做法,不过跟登陆的做法极为类似,只是换掉了登陆的url而已,不过这个qiandao必须在已登陆的前提下再进行签到。
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)
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=
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)
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=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)
else:
print "贴吧 : %s" %result
print '签到失败 : %s'%result.encode('utf-8')
print ''
当签到的基类构造好时我们就要构造下一步的子类了,但是在登陆基类我们已经派生出两个子类BaiduLogin和JishuzhaiLogin,来分别处理百度与姬宅的登陆,所以我们既需要从登陆的两个子类中继承需要的功能,又需要从签到基类中继承所需要的功能,所以我们采用多继承的方法。
在我们的TiebaQiandao类中,我们既继承了BaiduLogin类,又继承了Qiandao类,为了防止共同父类方法的多次调用,我们采用super来调用父类的方法。
super是采用mro方式处理多继承中共同方法的多次调用的问题的,所以为了运行良好,我们必须将所有的调用父类的形式都改为super
同时,由于新型类中,mro顺序是广度优先的,所以同层间的相同方法最好使用相同的参数个数,否则就可能报错,而且达不到我们想要的结果。关于这部分的讨论,搜索一下python的多继承
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)
return t
这两个函数是为了得到签到的表单项之一的tbs,我们从该贴吧的页面中获取信息,所以得先进入这个贴吧,
而贴吧url形式为http://tieba.baidu.com/f?kw=贴吧名,当然贴吧名需要处理为url能识别的形式,而且得从gbk码转换而来,由于我编码的统一为utf-8,所以要做进一步转换
同样用正则表达式将tbs挑捡出来
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)
j=json.loads(l)
l=.encode('utf-8') for i in j]
return l
getAllTiebaList是获取喜爱贴吧的方法,其中我注释的部分是我在准备篇中所说的第一种方法,即进入到个人主页中提取。。其中包含在target=_blank title=后面的即是贴吧名,不过后面多了一个吧字,在这里我们用rstrip将其消掉,字符串rstrip方法用于消去共同后缀,rstrip消去共同前缀,使用默认参数时消去空格
第二种方法,即在登陆前提下,进入个人的i贴吧,从中获取贴吧信息,而这个部分信息较为混杂,我们仔细查看,发现在响应的末尾有一组以脚本形式存储的信息,以$_likeForum开头的数据
我们先用re模块将字符串提取出来,注意$需要转义所以加\,然后用json模块将字串转化为我们能够直接用的对象,在这里面会生成一组列表,列表中每一项都是一个字典,包括了爱逛的贴吧的信息,这里我们暂且只用name这一对键值,同时用了列表推导的技巧生成了这个列表
def qiandao(self,tieba_name):
self.setData(kw=tieba_name,tbs=self.getTiebaTbs(tieba_name))
response=super(TiebaQiandao,self).qiandao()
return tieba_name,response
qiandao方法是对父类的签到方法的具体实现,对于贴吧签到而言,我们不仅需要登陆百度,而且还需要知道所要签到的贴吧名,在加上贴吧的tbs后,发送表单完成签到
同时返回贴吧名与响应的元组
def analyseQiandaoResult(self,tieba_name,response):
result=json.loads(response)
no=result['no']
error=result['error']
if no == 0:
result=result['data']['uinfo']
result=tieba_name.decode('utf-8')
else:
result=tieba_name,error
return no,result
analyseQiandaoResult方法正是为了分析qiandao方法返回响应的方法,它所需参数正好是签到返回的结果,而这个响应结果,直接是以json形式存储的,所以我们可以用json模块直接提取出来,其中no是返回代码,0即登陆成功,1101代表已经登陆,1007代表今天签到次数超过100次,error即错误说明。
如果签到成功,响应中data对应值即是一些个人排名啊,贴吧排名,贴吧目录等项,uinfo代表个人信息,我们这里只取个人信息保存。最终返回响应代码与一个打包好的字典作为返回结果
def printQiandaoResult(self,no,result):
if no == 0:
for key,value in self.result_list.items():
print "%s : %s" %(value,result)
else:
print "贴吧 : %s" %result
print '签到失败 : %s'%result.encode('utf-8')
print ''
从分析结果中我们最终打印出我们需要的结果。。这块就不多说了。
def qiandaoAll(self,*except_list):
self.qiandao_response_list=
return self.qiandao_response_list
qiandaoAll方法用于签到所有爱逛的贴吧,参数中except_list用于设定无需签到的贴吧,这里其实可以用多线程,不过仔细想想还是觉得略麻烦而且在gae上部署也很麻烦多以就放弃了
姬宅的签到与贴吧签到类似,只需要加上一个formhash即可提交。当然两者都需要先login,再qiandao
最后我们就可以来个一键签到了
#!/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()
将这个代码文件设为可执行,需要签到时运行即可
自动签到的主体部分就到此结束了。。。
下来一篇就是将如何将这个脚本部署在gae上,并且用计划任务在12点附近进行签到。。。不过gae要求只能有最多30s的响应时间所以12点刚过那阵贴吧签到各种Deadline exceeded。。。。几乎到快到20才能勉强签上。。不知为何。。暂时也没有用多线程。。难道只有用多线程才能改进一下么
恩恩。。下一篇就是部署到gae上,并进行少量优化
发帖果然理会的人不多啊。。。而且自己话也说不太清楚。。。自己第一次写教程也请各位见谅。。
再。。求发糖#18t
被站长发糖。。。洒家这辈子值了。。。。 好长,先MARK一个,明天再看 顶楼主,只是自己不喜欢urllib库什么的,感觉做的不太方便使用。
还是喜欢requests库,这个好像用起来,更省心 啊 langyxxl 发表于 2012-11-21 09:27 static/image/common/back.gif
顶楼主,只是自己不喜欢urllib库什么的,感觉做的不太方便使用。
还是喜欢requests库,这个好像用起来,更 ...
urllib2之类的确实麻烦,每次想要用都要先查一下
上次看到有人拿urllib2和requests做了下对比,果然requests好方便,不过自己还没尝试过requests 本帖最后由 langyxxl 于 2012-11-21 14:21 编辑
轻舟过 发表于 2012-11-21 13:30 static/image/common/back.gif
urllib2之类的确实麻烦,每次想要用都要先查一下
上次看到有人拿urllib2和requests做了下对比,果然reque ...
看完后,感触良深啊
依稀记得一年前看urllib库的时候,好痛苦啊,本来学python挺开心的,学到urllib时就揪心了
=1980= langyxxl 发表于 2012-11-21 14:15 static/image/common/back.gif
看完后,感触良深啊
好像那个人就是requests的作者,奉行极简主义,连ppt的风格都是那么简洁 先马克 langyxxl 发表于 2012-11-21 09:27 static/image/common/back.gif
顶楼主,只是自己不喜欢urllib库什么的,感觉做的不太方便使用。
还是喜欢requests库,这个好像用起来,更 ...
urllib2的确是略麻烦。。。不过requests作为第三方模块也不太好部署上去。写这个的时候基本只想着用标准模块了。。。不过在这之前我也不知道requests模块。。谢谢啦。。终于有一个较为简单的http模块了。。。 牛爆了 #6663!就。。先马着。。好了。。。 myrc707 发表于 2013-4-2 13:07 static/image/common/back.gif
就。。先马着。。好了。。。
这么多年前的东西都能翻的出来啊。。。。 赞 :42:好强大~ Sweet534 发表于 2013-4-2 14:29 static/image/common/back.gif
好强大~
话说今天是怎么了。。。久远的帖子被翻出来了。。。
页:
[1]
2