Discuz发帖器的实现

2009年11月11日  |  7:47 下午分类:python  |  标签:  |  

首先要清楚discuz论坛发帖的流程,简单地说就是以下流程:

进入登录页 ->登录 -> 进入版面 ->发帖

登录和发帖时要获取到页面的formhash值,否则会失败,如果启用了验证码,还得去分析验证码,这就比较复杂了。这里只用python来描述这一系列过程,涉及到验证码还请大家自行去实现。


#!/usr/bin/env python
#coding=utf-8
from urllib import urlencode
import cookielib, urllib2,urllib
import os,sys
import urllib2,cookielib,urllib,httplib,re

import getpass
import time

from Queue import Queue
import threading

class Discuz:
    def __init__(self,uid,pwd,debug = False,**param):
        self.username = uid
        self.password = pwd
        self.para = param

        #self.timelimit = timelimit
        self.regex = {
            'loginreg':'<input\s*type="hidden"\s*name="formhash"\s*value="([\w\W]+?)"\s*\/>',
            'postreg':'<input\s*type="hidden"\s*name="formhash"\s*id="formhash"\s*value="([\w\W]+?)"\s*\/>'
        }
        self.opener = None
        self.request = None
        self.islogin = False
        self.donecount = 0
        self.__login()
        self.threadcount = 10
    def __login(self):
        try:
            loginPage = urllib2.urlopen(self.para['loginurl']).read()
            formhash = re.search(self.regex['loginreg'],loginPage)
            formhash = formhash.group(1)
            print 'start login......'
            cookiejar = cookielib.CookieJar()
            self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
            values = {
                     'formhash':formhash,
                     'username':self.username,
                     'password':self.password,
                     'loginsubmit':'true'
                    }
            data = urllib.urlencode(values)
            self.request = urllib2.Request(self.para['loginsubmiturl'], data)
            rq = self.opener.open(self.request)

            print 'login success......'
            self.islogin = True
        except Exception ,e:
            print e
    def Post(self,subject,wysiwyg,content):
        threads = []
        for i in range(self.threadcount):
            t = threading.Thread(
                target=self.__postTopic,
                kwargs={'_subject':subject,'_wysiwyg':wysiwyg,'_body':content}
            )
            threads.append(t)
        for i in range(self.threadcount):
            threads[i].start()

        for i in range(self.threadcount):
            threads[i].join()
        print 'done'
    def __postTopic(self,**para):
        if not self.islogin:
            print 'please login......'
            return

        while True:
            try:
                self.request = urllib2.Request(self.para['posturl'])
                rq = self.opener.open(self.request)
                data = rq.read()

                formhash = re.search(self.regex['postreg'],data)
                formhash =  formhash.group(1)

                postdata = {
                    'addtags':'+可用标签',
                    'checkbox':'0',
                    'formhash':formhash,
                    'iconid':'',
                    'message':para['_body'],
                    'subject':para['_subject'],
                    'tags':'',
                    'updateswfattach' : '0',
                    'wysiwyg' : para['_wysiwyg']
                }
                self.request = urllib2.Request(self.para['postsubmiturl'],urllib.urlencode(postdata))
                self.opener.open(self.request)
                self.donecount+=1
                print '%d done.....' % self.donecount
            except Exception,e:
                print e
            time.sleep(2)

if __name__=='__main__':
    name = raw_input('username:')
    password = getpass.getpass('password:')
    dz = Discuz(name,password,
    loginurl='http://xxx/logging.php?action=login',
    loginsubmiturl='http://xxx/logging.php?action=login&loginsubmit=yes',
    posturl='http://xxx/post.php?action=newthread&fid=5',
    postsubmiturl='http://xxx/post.php?&action=newthread&fid=5&extra=&topicsubmit=yes')
    content='''这是帖子内容'''
    dz.Post('这是帖子标题','1',content)

Discuz类中只有一个公开方法
def Post(self,subject,wysiwyg,content)
三个参数,分别是帖子标题、是否是可视化编辑、帖子内容。
类实例化时会进行登录操作,并同时记录下cookie以备用,Post方法中会启用多个线程执行私有方法__postTopic(self,**para)进行真正的发帖操作。
所以,基本上Discuz生成的formhash就是一个鸡肋 -_-

转载时务必以超链接形式标明文章原始出处和作者信息。

1位领导已批示 关于 “Discuz发帖器的实现”

  1. 飞鱼 发表于: 十一月 14th, 2009 9:21 下午

    如果导出论坛列表群发。
    多个论坛站点如何处理。opener的Session是一个问题。

    不过学习了。最近也在研究这个。呵呵

    [回复Ta]


发表您的评论

2412151751091918111201478131663