Osmanthus

空想具現化


  • 首页
  • 归档
  • 分类
  • 标签
  • 关于
  •   

© 2024 Homurax

UV: | PV:

Theme Typography by Makito

Proudly published with Hexo

Python脚本 discuz论坛登录

发布于 2020-01-13 Python  脚本 

discuz 论坛登录还是比较简单的,而且通用性比较强。python代码中主要使用了 requests 库,简单易用。

登录简要步骤:

  • 获取loginhash、formhash
  • 如果涉及验证码,需要通过获取update值来获取图片,并且识别验证码和校验
  • 综合以上信息与账号验证信息,发送登录请求
import re
import requests


class DiscuzLogin:
    proxies = {
        'http': 'http://127.0.0.1:1080',
        'https': 'https://127.0.0.1:1080'
    }

    def __init__(self, hostname, username, password, questionid='0', answer=None, proxies=None):
        self.session = requests.session()
        self.hostname = hostname
        self.username = username
        self.password = password
        self.questionid = questionid
        self.answer = answer
        if proxies:
            self.proxies = proxies

    @classmethod
    def user_login(cls, hostname, username, password, questionid='0', answer=None, proxies=None):
        user = DiscuzLogin(hostname, username, password, questionid, answer, proxies)
        user.login()

    def form_hash(self):
        rst = self.session.get(f'https://{self.hostname}/member.php?mod=logging&action=login').text
        loginhash = re.search(r'<div id="main_messaqge_(.+?)">', rst).group(1)
        formhash = re.search(r'<input type="hidden" name="formhash" value="(.+?)" />', rst).group(1)
        return loginhash, formhash

    def login(self):
        loginhash, formhash = self.form_hash()
        login_url = f'https://{self.hostname}/member.php?mod=logging&action=login&loginsubmit=yes&loginhash={loginhash}&inajax=1'
        formData = {
            'formhash': formhash,
            'referer': f'https://{self.hostname}/',
            'loginfield': self.username,
            'username': self.username,
            'password': self.password,
            'questionid': self.questionid,
            'answer': self.answer,
            'cookietime': 2592000
        }
        login_rst = self.session.post(login_url, proxies=self.proxies, data=formData)
        if self.session.cookies.get('xxzo_2132_auth'):
            print(f'Welcome {self.username}!')
        else:
            raise ValueError('Verify Failed! Check your username and password!')


if __name__ == '__main__':
    DiscuzLogin.user_login('hostname', 'username', 'password')

DiscuzLogin 对象

DiscuzLogin.form_hash(): 获取loginhash、formhash

DiscuzLogin.login(): 发送登录请求

username: 用户名

password: 密码,根据 discuz 的设定,可能直接传递,也可能传递密码的 MD5 值

questionid: 验证问题的id,默认值即没有设置

answer: 验证问题的答案,默认为空

proxies: 代理信息,默认使用了ss,可以直接删去,亦可自行传入

如果请求发送的是密码的 MD5 值:

import hashlib


def md5(password):
    return hashlib.md5(password.encode(encoding='UTF-8')).hexdigest()

发送登录请求后,通过判断 cookies 中是否存在xxzo_2132_auth来判断是否登录成功。
如果登录验证失败,也可考虑把错误信息展示出来。

验证码

如果 discuz 设置开启了验证码,需要通过update的值来获取图片,获取、识别后可以通过验证接口来进行检查。这里略过图片中验证码的识别。

def update_value(self):
    rst = self.session.get(f'https://{self.hostname}/misc.php?mod=seccode&action=update&idhash=cS&0.3701502461393815&modid=member::logging').text
    update = re.search(r'update=(.+?)&idhash=', rst).group(1)
    return update

def get_code_png(self):
    code_headers = {
        'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Connection': 'keep-alive',
        'hostname': f'{self.hostname}',
        'Referer': f'https://{self.hostname}/member.php?mod=logging&action=login',
        'Sec-Fetch-Mode': 'no-cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
    }
    rst = self.session.get(f'https://{self.hostname}/misc.php?mod=seccode&update={self.update_value()}&idhash=cS',
                           headers=code_headers)
    with open('code.png', 'wb') as f:
        f.write(rst.content)

def check_code(self, code):
    check_rst = self.session.get(
        f'https://{self.hostname}/misc.php?mod=seccode&action=check&inajax=1&modid=member::logging&idhash=cS&secverify={code}')
    print(check_rst.text)

同时登录提交的表单中,要相应增加验证信息:

formData = {
    'seccodehash': 'cS',
    'seccodemodid': 'member::logging',
    'seccodeverify': '',  # verify code
}

 上一篇: MapStruct结合lombok使用 下一篇: pip离线安装依赖库 

© 2024 Homurax

UV: | PV:

Theme Typography by Makito

Proudly published with Hexo