Форум сайта python.su
Собрался, я, значится, свой говномесседжер для вконтактика запилить на pyqt. Само собой, все запросы к вк должны из отдельного потока идти, однако, вконтакт иногда запрашивает капчу, скотина эдакая. Кто-нибудь что-то подобное делал? С какой стороны к этой проблеме подойти вообще? Пока думаю для потока запросов использовать наследника QtCore.QThread с переопределённым run(), для работы с контактом - vk_api. Получается что-то такое:
#!/usr/bin/python3 ''' Created on 20 янв. 2017 г. @author: metallikus ''' from PyQt5 import QtCore, QtWidgets, Qt import vk_api import datetime import time class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) self.loginInput = QtWidgets.QLineEdit() self.passInput = QtWidgets.QLineEdit() self.urlInput = QtWidgets.QLineEdit() self.startButton = QtWidgets.QPushButton("spam!") self.setCentralWidget(QtWidgets.QWidget()) self.centralWidget().setLayout(QtWidgets.QVBoxLayout()) self.centralWidget().layout().addWidget(QtWidgets.QLabel("Логин:")) self.centralWidget().layout().addWidget(self.loginInput) self.centralWidget().layout().addWidget(QtWidgets.QLabel("Пароль:")) self.centralWidget().layout().addWidget(self.passInput) self.centralWidget().layout().addWidget(QtWidgets.QLabel("Url жертвы:")) self.centralWidget().layout().addWidget(self.urlInput) self.centralWidget().layout().addSpacerItem(QtWidgets.QSpacerItem(0, 5, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)) self.centralWidget().layout().addWidget(self.startButton) self.startButton.clicked.connect(self.startSpam) def startSpam(self): if (len(self.loginInput.text()) > 0 and len(self.passInput.text()) > 0 and len(self.urlInput.text()) > 0): self.msgSender = MsgSender(self.loginInput.text(), self.passInput.text(), self.urlInput.text()) self.msgSender.start() else: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, "egg", "Заполните все поля, пожалуйста!", QtWidgets.QMessageBox.Ok, self).show() class CaptchaWindow(QtWidgets.QWidget): def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) self.setLayout(QtWidgets.QVBoxLayout()) self.layout().addWidget(QtWidgets.QLabel("Капча вылезла!")) class MsgSender(QtCore.QThread): printTxt = QtCore.pyqtSignal(str) #сигнал для передачи текста родителю def __init__(self, login=None, password=None, url=None, parent=None): QtCore.QThread.__init__(self, parent) self.login = login self.password = password self.url = url def captchaHandler(self, captcha): key = """ Как-то запросить ввод капчи из гуи-потока, но, блин, как, мать его? """ print("Капча, блин") return captcha.try_again(key) def run(self): vk1 = vk_api.VkApi(self.login, self.password, captcha_handler=self.captchaHandler) vk1.authorization() screenName = self.url.strip().split("/")[-1] userId = vk1.method("users.get", {"user_ids": screenName})[0]["id"] while True: vk1.method("messages.send",{"user_id": userId, "message":datetime.datetime.now(), "random_id":int(datetime.datetime.now().timestamp())}) def run(): import sys app = Qt.QApplication(sys.argv) window = MainWindow() window.setWindowTitle("Заголовок") window.show() sys.exit(app.exec_()) if __name__ == "__main__": run()
Офлайн
Metallikus
А что тебе мешает в потоке отлавливать запрос капчи, извлекать картинку с капчой, передавать ее с помощью сигнала в главный поток, чтобы там попросить пользователя ввести код?
В общем тут все решает слотами и сигналами без каких либо проблем)
Офлайн
А назад из gui-потока как вбитый код передать? Да и поток должен стоять и ждать, пока капчу не введут.
Офлайн
Metallikus
Слоты и сигналы тебе в помощь. Я не представляю как можно кодить на qt и не знать об этом.
Офлайн
Но ведь если из гуя обратиться к слоту Qthread, то гуй повесится же. Обновлённый captchaHandler:
def captchaHandler(self, captcha): captchaFile = open(os.path.join(self.tmpFilesPath, "captcha.jpg"), "wb") captchaFile.write(captcha.get_image()) captchaFile.close() self.captchaNeeded.emit() #Передали сигнал в гуй, тот показал окошко, юзер вбил туда капчу "Как-то поставить поток на паузу, что ли..." "Как-то снять поток с паузы, когда капча вбита" key = "Вбитая юзером капча" print("Капча, блин") return captcha.try_again(key)
Офлайн
Парюсь похожим вопросом. Нашёл такую штуку, но не разобрался, может поможет Вам:
https://pythonworld.ru/moduli/modul-subprocess.html - фишка в timeout
Можно поизучать код программы тетрис (https://pythonworld.ru/gui/pyqt5-tetris.html ) - в коде есть функция паузы.
Есть ещё модуль time, но думаю, он не подходит.
Отредактировано Kyrym (Янв. 23, 2017 10:46:06)
Офлайн
В общем, я хз, так или не так делаются подобные вещи, но пока работает:
В __init__ спам-потока:
self.mutex = Qt.QMutex() #хз зачем эта штука, но без неё не работает self.captchaInputed = Qt.QWaitCondition() #паузатор
def captchaHandler(self, captcha): captchaFile = open("captcha.jpg", "wb") captchaFile.write(captcha.get_image()) captchaFile.close() self.captchaNeeded.emit() #Передали сигнал в гуй, тот показал окошко, юзер вбил туда капчу self.captchaInputed.wait(self.mutex) #ждём, пока кто-нить не сделает captchaInputed.wake-сколько-нибудь #продолжаем после вызова captchaInputed.wakeAll() из гуя key = self.key return captcha.try_again(key)
def run(self): self.mutex.lock()
Отредактировано Metallikus (Янв. 23, 2017 11:15:13)
Офлайн