|  | 
 
| 
代码太长,我没写注释,问chatgpt他说我代码太长不肯回我
x
马上注册,结交更多好友,享用更多功能^_^您需要 登录 才可以下载或查看,没有账号?立即注册    
 复制代码import pygame
from selenium import webdriver
from requests import get
from subprocess import getstatusoutput as _gsout
from threading import Thread, Timer
from os import remove
from os.path import isfile
from pickle import load, dump
from time import sleep
from bs4 import BeautifulSoup
from lxml import html
pygame.init()
pygame.key.set_repeat(1000, 50)
class Button(pygame.sprite.Sprite):
    def __init__(self, name, size, font: pygame.font.Font, bgc, fgc, pos, key='\0'):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface(size)
        self.image.fill(bgc)
        surf = font.render(name, False, fgc)
        rect = surf.get_rect()
        rect.center = self.image.get_rect().center
        self.image.blit(surf, rect)
        self.rect = self.image.get_rect()
        self.rect.topleft = pos
        self.key = key
        self.font = font
        self.bgc = bgc
        self.fgc = fgc
    
    def chosen(self, event: pygame.event.Event):
        if event.type == pygame.MOUSEBUTTONUP:
            if self.rect.collidepoint(event.pos):
                return True
        if event.type == pygame.KEYDOWN:
            if event.key == ord(self.key) and event.mod & pygame.KMOD_ALT:
                return True
        return False
    def draw(self):
        screen.blit(self.image, self.rect)
class Text(pygame.sprite.Sprite):
    def __init__(self, text, font, color, pos):
        pygame.sprite.Sprite.__init__(self)
        self.font = font
        self._text = text
        self.color = color
        self.image = self.font.render(self.text, False, self.color)
        self.rect = self.image.get_rect()
        self.rect.topleft = pos
    
    def draw(self):
        screen.blit(self.image, self.rect)
    @property
    def text(self):
        return self._text
    @text.setter
    def text(self, new):
        self._text = new
        self.image = self.font.render(self.text, False, self.color)
class Entry(pygame.sprite.Sprite):
    def __init__(self, size, font, bgc, bdc, fgc, pos):
        pygame.sprite.Sprite.__init__(self)
        self.bgc = bgc
        self.bdc = bdc
        self.image = pygame.Surface(size)
        self.image.fill(bgc)
        for x in range(0, size[0]):
            self.image.set_at((x, 0), bdc)
            self.image.set_at((x, size[1] - 1), bdc)
        for y in range(0, size[1]):
            self.image.set_at((0, y), bdc)
            self.image.set_at((size[0] - 1, y), bdc)
        self.text = Text('', font, fgc, pos)
        self.image.blit(self.text.image, (0, 0))
        self.rect = self.image.get_rect()
        self.rect.topleft = pos
        self.selected = False
    
    @property
    def fgc(self):
        return self.text.color
    def draw(self):
        screen.blit(self.image, self.rect)
    
    def listen(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            self.selected = self.rect.collidepoint(event.pos)
        elif event.type == pygame.KEYDOWN:
            if self.selected:
                if event.key == pygame.K_BACKSPACE:
                    self.text.text = self.text.text[:-1]
                    self._update_text()
                elif (event.unicode in 
                    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[];,./{}|:"<>?'
                    + "'" + '\\'
                ):
                    self.text.text += event.unicode
                    self._update_text()
    
    def _update_text(self):
        size = self.rect.size
        self.image = pygame.Surface(size)
        self.image.fill(self.bgc)
        for x in range(0, size[0]):
            self.image.set_at((x, 0), self.bdc)
            self.image.set_at((x, size[1] - 1), self.bdc)
        for y in range(0, size[1]):
            self.image.set_at((0, y), self.bdc)
            self.image.set_at((size[0] - 1, y), self.bdc)
        self.text = Text(self.text.text, self.text.font, self.fgc, self.rect.topleft)
        self.image.blit(self.text.image, (0, 0))
class PasswordEntry(Entry):
    def _update_text(self):
        size = self.rect.size
        self.image = pygame.Surface(size)
        self.image.fill(self.bgc)
        for x in range(0, size[0]):
            self.image.set_at((x, 0), self.bdc)
            self.image.set_at((x, size[1] - 1), self.bdc)
        for y in range(0, size[1]):
            self.image.set_at((0, y), self.bdc)
            self.image.set_at((size[0] - 1, y), self.bdc)
        self.text = Text(len(self.text.text) * '*', self.text.font, self.fgc, self.rect.topleft)
        self.image.blit(self.text.image, (0, 0))
class MyThread(Thread):
    def __init__(self, func, args=(), kwargs=None, timeout=None):
        Thread.__init__(self)
        self.func = func
        self.args = args
        self.kwargs = {} if kwargs is None else kwargs
        self.timeout = timeout
        self.result = None
    
    def run(self):
        self.result = self.func(*self.args, **self.kwargs)
def timeout(seconds):
    def decorated(func):
        def done(*args, **kwargs):
            err = None
            result = None
            def inner():
                nonlocal err, result
                try:
                    result = func(*args, **kwargs)
                except BaseException as msg:
                    err = msg
            thread = Thread(target=inner)
            thread.start()
            # 只等待seconds秒
            thread.join(seconds)
            # 如果线程还活着
            if thread.is_alive():
                raise TimeoutError
            if err:
                raise err
            return result
        return done
    return decorated
# 实际上是生成了一个新的decorated函数,通过闭包的形式保存了秒数,然后done里再调用inner
@timeout(1)
def soutf(msg):
    return _gsout(msg)
def check_internet():
    try:
        soutf('ping fishc.com.cn')
        # 这东西,报错可是最快
        print('你没联网')
        exit()
    except TimeoutError:
        # 连上了的话那就好说
        pass
def load_image(url):
    filename = 'temp.png'
    with open(filename, 'wb') as f:
        f.write(get(url, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
        }).content)
    image = pygame.image.load(filename)
    remove(filename)
    return image
def save():
    with open('fishc.set', 'wb') as f:
        dump(data, f)
def loginf(email, password):
    driver.get('https://fishc.com.cn/member.php?mod=logging&action=login')
    sleep(1)
    driver.find_element(
        'xpath',
        '/html/body/div[6]/div/div[2]/div/div[2]/div[1]/div[1]/form/div/div[1]/table/tbody/tr/td[1]/input'
    ).send_keys(email)
    driver.find_element(
        'xpath',
        '/html/body/div[6]/div/div[2]/div/div[2]/div[1]/div[1]/form/div/div[2]/table/tbody/tr/td[1]/input'
    ).send_keys(password)
    driver.find_element(
        'xpath',
        '/html/body/div[6]/div/div[2]/div/div[2]/div[1]/div[1]/form/div/div[6]/table/tbody/tr/td[1]/button'
    ).click()
    sleep(1)
    driver.find_element('id', 'succeedmessage_href').click()
    return driver.page_source
def getdata(source):
    tree = html.fromstring(source)
    part = html.tostring(tree.xpath('//strong[@class="vwmy"]')[0], encoding='unicode')
    usergroup = html.tostring(tree.xpath('//a[@id="g_upmine"]')[0], encoding='unicode')
    soup = BeautifulSoup(part, features='lxml')
    soup2 = BeautifulSoup(usergroup, features='lxml')
    return soup.find('a').text, soup2.find('font').get('color'), soup2.find('font').text
def login_to1(email, password):
    return getdata(loginf(email, password))
def login_to(email, password):
    result = login_to1(email, password)
    Timer(3, hide_msg).start()
    return result
def hide_msg():
    global state
    state = 3
check_internet()
size = width, height = (640, 480)
screen = pygame.display.set_mode(size)
logo = load_image('https://fishc.com.cn/static/image/common/logo.png')
icon = load_image('https://fishc.com.cn/favicon.ico')
pygame.display.set_caption('FishC App')
pygame.display.set_icon(icon)
font15 = pygame.font.SysFont('microsoftyaheiui', 15)
font20 = pygame.font.SysFont('microsoftyaheiui', 20)
font20b = pygame.font.SysFont('microsoftyaheiui', 20)
font20b.set_bold(True)
chrome = Button('[C]hrome', (100, 50), font20, (0, 255, 0), (0, 0, 0), (100, 200), 'c')
firefox = Button('[F]irefox', (100, 50), font20, (0, 255, 0), (0, 0, 0), (300, 200), 'f')
c_chrome = Button('Change driver(Using Chrome)', (200, 50), font15, (255, 255, 255), (0, 0, 0), (width - 200, 0))
c_firefox = Button('Change driver(Using Firefox)', (200, 50), font15, (255, 255, 255), (0, 0, 0), (width - 200, 0))
change = c_chrome
login = Button('登录(L)', (100, 50), font20, (0, 0, 255), (255, 255, 255), (width - 123, height - 100), 'l')
save1 = Button('保存数据(S)', (150, 50), font20, (0, 0, 255), (255, 255, 255), (width // 2 - 125, height // 2 - 50), 's')
unsave = Button('不保存数据(N)', (150, 50), font20, (0, 0, 255), (255, 255, 255), (width // 2 - 125, height // 2 + 50), 'n')
swin = pygame.Rect(width // 4, height // 4, width // 2, height // 2)
username = Entry((200, 30), font20, (255, 255, 255), (0, 0, 127), (0, 0, 0), (200, 100))
pwd = Entry((200, 30), font20, (255, 255, 255), (0, 0, 127), (0, 0, 0), (200, 180))
t_user = Text('用户名/邮箱', font20b, (0, 0, 0), (90, 100))
t_pwd = Text('密码', font20b, (0, 0, 0), (100, 180))
logining = Text('', font15, (0, 0, 0), (300, 200))
succed = Text('', font15, (0, 0, 0), (width - 150, 10))
data = {
    'driver': None,
    'username': None,
    'password': None
}
state = 0
if isfile('fishc.set'):
    with open('fishc.set', 'rb') as f:
        data = load(f)
thread = None
clock = pygame.time.Clock()
running = True
while running:
    clock.tick(30)
    screen.fill((255, 255, 255))
    screen.blit(logo, (0, 0))
    if state == 1:
        pygame.draw.rect(screen, (0, 0, 0), swin, 2)
        save1.draw()
        unsave.draw()
    elif state == 0:
        if data['driver'] is None:
            chrome.draw()
            firefox.draw()
        else:
            change.draw()
            if data['username'] is None or data['password'] is None:
                username.draw()
                t_user.draw()
                pwd.draw()
                t_pwd.draw()
                login.draw()
    elif state == 2:
        if thread.result is None:
            logining.text = '登录中...'
        else:
            logining.text = '登录成功!'
        logining.draw()
    elif state == 3:
        succed.text = f'{thread.result[0]}(用户组: {thread.result[2]})'
        succed.color = thread.result[1]
        succed.rect.topleft = (width - succed.rect.width - 10, 10)
        succed.draw()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            if state == 1:
                running = False
                # 虽然只会退出for
                break
            state = 1
        if state == 1:
            if save1.chosen(event):
                save()
                running = False
            elif unsave.chosen(event):
                running = False
        else:
            if data['driver'] is None:
                temp = False
                if chrome.chosen(event):
                    data['driver'] = (webdriver.Chrome, webdriver.ChromeOptions)
                    change = c_chrome
                    temp = True
                elif firefox.chosen(event):
                    data['driver'] = (webdriver.Firefox, webdriver.FirefoxOptions)
                    change = c_firefox                
                    temp = True
                if temp:
                    option = data['driver'][1]()
                    option.add_argument('headless')
                    driver = data['driver'][0](options=option)
            else:
                if data['username'] is None or data['password'] is None:
                    username.listen(event)
                    pwd.listen(event)
                if change.chosen(event):
                    data['driver'] = None
                if login.chosen(event):
                    data['username'] = username.text.text
                    data['password'] = pwd.text.text
                    state = 2
                    thread = MyThread(func=login_to, args=(username.text.text, pwd.text.text))
                    thread.start()
    pygame.display.flip()
pygame.quit()
driver.close()
就这么一个文件
 
  main1.zip
(3.61 KB, 下载次数: 1) picture:
   
抱歉,看起来是文本的渲染方式导致的。为了使文本更精确地居中,可以在绘制文本前计算文本宽度的一半,并将其减去屏幕宽度的一半。这样可以确保文本在屏幕中心位置上。修改代码如下:
 1. 在  Text  类中添加一个方法  draw_centered ,用于计算并绘制居中的文本:
 
 
 复制代码class Text:
    # 省略其他代码...
    def draw_centered(self, surface):
        self.surface = self.font.render(self.text, True, self.color)
        self.rect = self.surface.get_rect()
        self.rect.center = (width // 2, height // 2)
        surface.blit(self.surface, self.rect.topleft)
 2. 更新  state == 3  的情况,使用新的  draw_centered  方法绘制居中的文本:
 
 
 复制代码elif state == 3:
    succed.text = f'{thread.result[0]}(用户组: {thread.result[2]})'
    succed.color = thread.result[1]
    succed.draw_centered(screen)
 这样,当登录成功后,用户名和用户组信息将准确显示在屏幕正中间。
 | 
 |