From 939d83907998bc635f5e4aa8f44eb827f0e83fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Gl=C3=BCpker?= Date: Wed, 23 Mar 2016 09:15:40 +0100 Subject: Implement captchaclicking for another captcha type Try to detect, which image is provided, by checking some pixels for values. The first captcha has a big, black infopanel and an example image with a white border. The second captcha has a small info panel and we're testing for a nearly black pixel (jpeg artefacts...) for the corresponding imagenumbers --- 9kwpyqt.py | 130 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 35 deletions(-) diff --git a/9kwpyqt.py b/9kwpyqt.py index d676013..29e9d28 100755 --- a/9kwpyqt.py +++ b/9kwpyqt.py @@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtWidgets import QLayout, QHBoxLayout, QVBoxLayout, QSizePolicy from PyQt5.QtWidgets import QLabel, QLineEdit, QPushButton, QProgressBar -from PyQt5.QtGui import QPixmap +from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtMultimedia import QSound from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply @@ -14,40 +14,109 @@ API_URL = "http://www.9kw.eu/index.cgi" API_KEY = "" soundfile = "notify.wav" -class ExtendedQLabel(QLabel): +class PixelInfo(): + pixelA = 0 + pixelR = 0 + pixelG = 0 + pixelB = 0 + + def __init__(self, argb): + self.pixelB = argb & 0xff + argb = argb >> 8 + self.pixelG = argb & 0xff + argb = argb >> 8 + self.pixelR = argb & 0xff + argb = argb >> 8 + self.pixelA = argb & 0xff + + def isLower(self, r, g, b): + return (self.pixelR < r and self.pixelG < g and self.pixelB < b) + + def isHigher(self, r, g, b): + return (self.pixelR > r and self.pixelG > g and self.pixelB > b) - clicked = pyqtSignal(int) + def isExactly(self, r, g, b): + return (self.pixelR == r and self.pixelG == g and self.pixelB == b) + + + +class ExtendedQLabel(QLabel): + clicked = pyqtSignal(int, str) + image = False # QPixmap() + imageR = False # QPixmap() resized + imageB = False # QImage() def __init(self, parent): QLabel.__init(self, parent) + def setImage(self, image): + self.image = image + self.imageR = self.image.scaled(self.size(), + Qt.KeepAspectRatio) + self.imageB = False + self.setPixmap(self.imageR) + + def removeImage(self, image): + self.image = False + self.imageR = False + self.imageB = False + QLabel.setPixmap(QPixmap()) + + def resizeEvent(self, evt=None): + QLabel.resizeEvent(self, evt) + if self.image: + self.imageR = self.image.scaled(self.size(), + Qt.KeepAspectRatio) + self.setPixmap(self.imageR) + def mouseReleaseEvent(self, ev): - if not self.pixmap(): + if not self.image: return + if not self.imageB: + self.imageB = self.image.toImage() # get size of pixmap imgx = self.pixmap().size().width() imgy = self.pixmap().size().height() - # get cursor size relative to pixmap + # get cursor position relative to pixmap ((0,0) = topleft) x = ev.pos().x() - self.size().width() / 2 + imgx/2 y = ev.pos().y() - self.size().height() / 2 + imgy/2 - # check if on pixmap (upper 19% = info) - if x > imgx or y > imgy or x < 0 or y < 0.19*imgy: - print("Not on image") - return - # which piece is below the mouse? - xpiece = x // (imgx / 3) + 1 - ypiece = (y-0.19*imgy) // (imgy*0.81 / 3) + # Which type of captcha is this image? + if PixelInfo(self.imageB.pixel(90, 45)).isExactly(0,0,0) and \ + PixelInfo(self.imageB.pixel( 5, 30)).isHigher(220,220,220) and \ + PixelInfo(self.imageB.pixel(71, 30)).isHigher(220,220,220) and \ + PixelInfo(self.imageB.pixel(40, 5)).isHigher(220,220,220) and \ + PixelInfo(self.imageB.pixel(40, 59)).isHigher(220,220,220): + # check if on pixmap (upper 17.5% = infopanel) + if x > imgx or y > imgy or x < 0 or y < 0.175*imgy: + return + xpiece = x // (imgx / 3) + 1 + ypiece = (y-0.175*imgy) // (imgy*0.825 / 3) + self.clicked.emit(3*ypiece+xpiece, ",") + + elif PixelInfo(self.imageB.pixel( 16, 47)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(144, 47)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(269, 47)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel( 16, 172)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(144, 172)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(269, 172)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel( 16, 298)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(144, 298)).isLower(20,20,20) and \ + PixelInfo(self.imageB.pixel(269, 298)).isLower(20,20,20): + # check if on pixmap (upper 7% = infopanel) + if x > imgx or y > imgy or x < 0 or y < 0.0735*imgy: + return + xpiece = x // (imgx / 3) + 1 + ypiece = (y-0.0735*imgy) // (imgy*0.9265 / 3) + self.clicked.emit(3*(2-ypiece)+xpiece, "") + - self.clicked.emit(3*ypiece+xpiece) class CaptchaGUI(QWidget): sound = False # QSound() - image = False # QPixmap() - imageR = False # QPixmap() resized timer = False # QTimer() for 30sec timing running = False @@ -153,17 +222,12 @@ class CaptchaGUI(QWidget): ################################################## # Handle gui ################################################## - def resizeEvent(self, evt=None): - if self.image: - self.imageR = self.image.scaled(self.captchaImage.size(), - Qt.KeepAspectRatio) - self.captchaImage.setPixmap(self.imageR) - - def captchaClicked(self, clickedpiece): - if self.image: - text = self.captchaInputLine.text() - text += str(clickedpiece) - self.captchaInputLine.setText(text) + def captchaClicked(self, clickedpiece, separator): + text = self.captchaInputLine.text() + if len(text) > 0 and separator: + text += separator + text += str(clickedpiece) + self.captchaInputLine.setText(text) def updateStats(self): if self.startCredits: @@ -190,10 +254,7 @@ class CaptchaGUI(QWidget): pixmap = QPixmap() result = pixmap.loadFromData(image) if result: - self.image = pixmap - self.imageR = self.image.scaled(self.captchaImage.size(), - Qt.KeepAspectRatio) - self.captchaImage.setPixmap(self.imageR) + self.captchaImage.setImage(pixmap) self.captchaInputLine.setFocus() self.sound.play() self.timer.start(30000) @@ -203,8 +264,7 @@ class CaptchaGUI(QWidget): self.skipCaptcha() def removeCaptchaImage(self): - self.image = False - self.captchaImage.setPixmap(QPixmap()) + self.captchaImage.removeImage() def toggleRunning(self): self.running = not self.running @@ -213,9 +273,9 @@ class CaptchaGUI(QWidget): self.startstopButton.setText(self.running and "Stop" or "Start") self.startstopButton.setChecked(self.running) - def saveImage(self): - if self.image: - self.image.save("captcha-"+str(time.time())+".jpg") + # def saveImage(self): + # if self.image: + # self.image.save("captcha-"+str(time.time())+".jpg") ################################################## # Handle network -- cgit v1.2.3