[Python代码]Discuz!论坛(X2.5)模拟登录脚本
Discuz!论坛是国内使用最广泛的论坛系统之一,目前最新的版本是X2.5。本文将介绍Discuz! X2.5版本系统模拟登录的Python脚本实现。
首先,我们来查看一下登录时传输的数据包中的post数据有哪些:
其中,formhash是一个验证数据,在登录前后不同,登录前的formhash可以忽略,但登录后的formhash需要读取出来,否则发帖时会提示“您的来路请求不正确”的错误。
referer是登录后跳转到的目的网页,不过由于登录后会出现登录成功/失败的提示信息,5s后才会转到目的网页,因此,这里的referer我们不去实现。
loginfield分为username(用户名登录)、uid(uid登录)和email(email登录)三种,不同论坛开启的可用登录方式可能不同,这里我们只去实现username登录。
username是用户名。password是密码,部分论坛可能会对密码进行了hash处理,不过post时不需要使用hash后的密码。questionid是安全提问,默认是0。answer是安全提问的答案,默认是空字符串。
cookietime是保留cookies的时间,默认是2592000(30天)。
在下面的代码中,loginfiled设置为username,cookietime设置为默认的2592000。用户执行login操作时,需要提供的参数包括username、password两个必填项和questionid、answer两个可选项。
下面这段代码来自文件config.py,是一些静态参数的设置文件。
1 2 3 4 5 6 7 8 9 10 11 12 |
# -*- coding: utf-8 -*- DOMAIN = r'http://localhost/dzx25/' USERNAME = r'admin' PASSWORD = r'admin' LOGINFIELD = r'username' COOKIETIME = 2592000 HOMEURL = DOMAIN + r'forum.php' LOGINURL = DOMAIN + r'member.php?mod=logging&action=login&loginsubmit=yes&frommessage&inajax=1' |
需要注意的是,如果用户名为汉字,需要在r前面加u。
下面的代码来自文件discuz.py,是discuz基类所在文件,提供构造函数、登录函数等基础方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# -*- coding: utf-8 -*- import urllib import urllib2 import cookielib import re import config class Discuz(object): def __init__(self): self.operate = '' # response的对象(不含read) self.formhash = '' # 没有formhash不能发帖 self.cj = cookielib.CookieJar() self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj)) urllib2.install_opener(self.opener) self.formhash_pattern = re.compile(r'<input type="hidden" name="formhash" value="([0-9a-zA-Z]+)" />') def login(self, username, password, questionid = 0, answer = ''): postdata = { 'loginfield': config.LOGINFIELD, 'username': username, 'password': password, 'questionid': questionid, 'answer': answer, 'cookietime': config.COOKIETIME, } login_success_pattern = re.compile(ur"\('succeedlocation'\).innerHTML = '(?u)(.+),现在将转入登录前页面';") login_fail_pattern = re.compile(r"{errorhandle_\('(?u)(.+)', {'loginperm':") # 取得登录成功/失败的提示信息 self.operate = self._get_response(config.LOGINURL, postdata) login_tip_page = self.operate.read().decode('utf-8') login_success_info = login_success_pattern.search(login_tip_page) login_fail_info = login_fail_pattern.search(login_tip_page) # 显示登录成功/失败信息 if login_success_info: print login_success_info.group(1) self.formhash = self._get_formhash(self._get_response(config.HOMEURL).read()) return True elif login_fail_info: print login_fail_info.group(1) else: print '无法获取登录状态' return False def _get_response(self, url, data = None): if data is not None: req = urllib2.Request(url, urllib.urlencode(data)) else: req = urllib2.Request(url) response = self.opener.open(req) return response def _get_formhash(self, page_content): self.formhash = self.formhash_pattern.search(page_content.decode('utf-8')).group(1) return self.formhash |
下面的代码是一个登录demo,来自login.py。
1 2 3 4 5 6 7 8 |
# -*- coding: utf-8 -*- import config import discuz if __name__ == '__main__': my_account = discuz.Discuz() my_account.login(config.USERNAME, config.PASSWORD) |
这样,我们就实现了discuz!论坛(X2.5版本)的登录操作,并且得到了登录成功/失败的提示信息。如果要执行发帖、获取页面等操作,就可以在这个的基础上进行编程了。
验证码怎么破。。。。
验证码没有弄过
请问上面那个查询postdata和formhash等等的是什么软件或插件?
httpfox
[Python代码]Discuz!论坛(X2.5)发帖及回复脚本这个打不开?
可以打开的啊
楼主,为何 login_fail_pattern = re.compile(r”{errorhandle_\(‘(?u)(.+)’, {‘loginperm’:”) 这串代码中的 \(‘(?u)(.+)’, {‘loginperm’: 在我python中提示有错误,有红色的波浪线。
但测试登录和发都能成功?
红色的波浪线是单词检测吧?
再问下,这个正则是按照哪个页面的源代码写的呢?想看下,对比下
请求的URL就是上面的LOGINURL,response可以看到一个xml。
刚才看了下其他的版本好像都不太一样:
比如X3.2是“{errorhandle_login(‘原因’, {});”这样的,
X3.1是{errorhandle_ls(‘原因’, {‘loginperm’:’4′});}
谢谢。再问下,(?u) 这个正则表示什么?去年也能用,因我看了下,是用(.+)这个来匹配字符串的。
这个是正则表达式的Unicode匹配原则。Python2中默认使用的是ASCII匹配原则,使用(?u)可以采用Unicode匹配原则。
在ASCII匹配原则下,\w可以匹配[0-9a-zA-Z_],而在Unicode匹配原则下,\w还可以匹配全角数字、中文字符等。
例如:
re.search(r”^\w$”, u”发”) != None # => False
re.search(r”^(?u)\w$”, u”发”) != None # => True
可以参考一下《正则指引》7.3节。
好的,谢谢。。我也终于知道为什么有红波浪丝了,因为{ 这个花括号没用转义符 \
你好 有个问题需求求助下,
DZ 给已有帖子 添加标签, 抓包得到的格式很奇怪,完全不知道 怎么下手,
——WebKitFormBoundaryIgbWtbYgHQbbFtFl
Content-Disposition: form-data; name=”formhash”
afd10a59
怎么构造啊。。。。
这个是multipart/form-data格式的,一般用于文件上传,不是比较好处理的application/x-www-form-urlencoded。
可以使用requests库,POST中包含一个files参数即可:
requests.post(‘url’, files={})
可能也有用的库还有mimetools、MultipartPostHandler。
当然也可以自己构造data的值,格式为:
每组POST参数为
–{boundary}\r\n
Content-Disposition: form-data; name=”{post_name}”\r\n
\r\n
{value_body}\r\n
最后以–{boundary}–结尾。
感谢及时回复
files={} 这个怎么构造 报错。。。
可以把你的data里的参数都写在files里,格式是:
files={‘key1’: (None, ‘value1’), ‘key2’: (None, ‘value2’)}
data里面可以不写东西,当然也可以只写一个在files里,剩下的在data里,或者files里随意写一个东西。
可以参考这个:http://stackoverflow.com/questions/23120974/python-requests-post-multipart-form-data-without-filename-in-http-request
你好 按照这个方法 返回结果是 主题不存在。。。。。
这是抓到的包
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”formhash”
b3aaf390
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”posttime”
1422451013
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”delattachop”
0
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”wysiwyg”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”fid”
63
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”tid”
37137
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”pid”
589084
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”page”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”typeid”
177
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”subject”
测试
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”message”
测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下测试一下
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”replycredit_extcredits”
0
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”replycredit_times”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”replycredit_membertimes”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”replycredit_random”
100
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”readperm”
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”price”
0
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”tags”
你好测试,嗄,爱上
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”allownoticeauthor”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”usesig”
1
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”delete”
0
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”save”
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”uploadalbum”
212
——WebKitFormBoundarySezkZq1fliPgEIsC
Content-Disposition: form-data; name=”newalbum”
请输入相册名称
——WebKitFormBoundarySezkZq1fliPgEIsC–
我构造了这几个:
post = “http://网址/forum.php?mod=post&action=edit&extra=&editsubmit=yes”
requests.post(post,
files={‘formhash’:(None,’b3aaf390′),’tags’: (None,’12345′),
‘fid’:(None,’63’),’tid’:(None,’37137′),’pid’:(None,’589084′),’page’:(None,’1′),’typeid’:(None,’177′),’uploadalbum’:(None,’212′)
},headers=headers,cookies=cookies)
然后 提示这个 抱歉,指定的主题不存在或已被删除或正在被审核
boundary前后的-是两个,具体的可以查看RFC1867 (http://www.ietf.org/rfc/rfc1867.txt) 的 6. Examples
你好 这个 数据表里面的 要全部添加才能使用吗?
你说的是哪个数据表?具体的参数你可以请求一次看下
这个代码显示 是什么插件 好漂亮哈哈
Crayon Syntax Highlighter
试了这么久 还是不会, 希望大神能帮助下