diff options
Diffstat (limited to 'module/plugins/captcha')
-rw-r--r-- | module/plugins/captcha/AdYouLike.py | 107 | ||||
-rw-r--r-- | module/plugins/captcha/AdsCaptcha.py | 77 | ||||
-rw-r--r-- | module/plugins/captcha/GigasizeCom.py | 24 | ||||
-rw-r--r-- | module/plugins/captcha/LinksaveIn.py | 158 | ||||
-rw-r--r-- | module/plugins/captcha/NetloadIn.py | 29 | ||||
-rw-r--r-- | module/plugins/captcha/ReCaptcha.py | 73 | ||||
-rw-r--r-- | module/plugins/captcha/ShareonlineBiz.py | 39 | ||||
-rw-r--r-- | module/plugins/captcha/SolveMedia.py | 50 | ||||
-rw-r--r-- | module/plugins/captcha/__init__.py | 1 | ||||
-rw-r--r-- | module/plugins/captcha/captcha.py | 319 |
10 files changed, 308 insertions, 569 deletions
diff --git a/module/plugins/captcha/AdYouLike.py b/module/plugins/captcha/AdYouLike.py new file mode 100644 index 000000000..bfb8b5ccb --- /dev/null +++ b/module/plugins/captcha/AdYouLike.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- + +import re + +from pyload.plugin.Captcha import Captcha +from pyload.utils import json_loads + + +class AdYouLike(Captcha): + __name__ = "AdYouLike" + __type__ = "captcha" + __version__ = "0.02" + + __description__ = """AdYouLike captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' + CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' + + + def detect_key(self, html=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("AdYouLike html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + m = re.search(self.AYL_PATTERN, html) + n = re.search(self.CALLBACK_PATTERN, html) + if m and n: + self.key = (m.group(1).strip(), n.group(1).strip()) + self.plugin.logDebug("AdYouLike ayl|callback: %s | %s" % self.key) + return self.key #: key is the tuple(ayl, callback) + else: + self.plugin.logDebug("AdYouLike ayl or callback not found") + return None + + + def challenge(self, key=None): + if not key: + if self.detect_key(): + key = self.key + else: + errmsg = _("AdYouLike key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + ayl, callback = key + + # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, + # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + ayl = json_loads(ayl) + + html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", + get={'key' : ayl['adyoulike']['key'], + 'env' : ayl['all']['env'], + 'callback': callback}) + try: + challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) + except Exception: + errmsg = _("AdYouLike challenge pattern not found") + self.plugin.error(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("AdYouLike challenge: %s" % challenge) + + return self.result(ayl, challenge) + + + def result(self, server, challenge): + # Adyoulike.g._jsonp_5579316662423138 + # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, + # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], + # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", + # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" + # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256, + # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, + # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, + # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) + + if isinstance(server, basestring): + server = json_loads(server) + + if isinstance(challenge, basestring): + challenge = json_loads(challenge) + + try: + instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] + result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() + except Exception: + errmsg = _("AdYouLike result not found") + self.plugin.error(errmsg) + raise ValueError(errmsg) + + result = {'_ayl_captcha_engine' : "adyoulike", + '_ayl_env' : server['all']['env'], + '_ayl_tid' : challenge['tid'], + '_ayl_token_challenge': challenge['token'], + '_ayl_response' : response} + + self.plugin.logDebug("AdYouLike result: %s" % result) + + return result diff --git a/module/plugins/captcha/AdsCaptcha.py b/module/plugins/captcha/AdsCaptcha.py new file mode 100644 index 000000000..5c01a422e --- /dev/null +++ b/module/plugins/captcha/AdsCaptcha.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +import re + +from random import random + +from pyload.plugin.Captcha import Captcha + + +class AdsCaptcha(Captcha): + __name__ = "AdsCaptcha" + __type__ = "captcha" + __version__ = "0.06" + + __description__ = """AdsCaptcha captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)' + PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)' + + + def detect_key(self, html=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("AdsCaptcha html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + m = re.search(self.PUBLICKEY_PATTERN, html) + n = re.search(self.CAPTCHAID_PATTERN, html) + if m and n: + self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) + self.plugin.logDebug("AdsCaptcha key|id: %s | %s" % self.key) + return self.key + else: + self.plugin.logDebug("AdsCaptcha key or id not found") + return None + + + def challenge(self, key=None): + if not key: + if self.detect_key(): + key = self.key + else: + errmsg = _("AdsCaptcha key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + PublicKey, CaptchaId = key + + html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", get={'CaptchaId': CaptchaId, 'PublicKey': PublicKey}) + try: + challenge = re.search("challenge: '(.+?)',", html).group(1) + server = re.search("server: '(.+?)',", html).group(1) + except Exception: + errmsg = _("AdsCaptcha challenge pattern not found") + self.plugin.error(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge) + + return challenge, self.result(server, challenge) + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, + get={'cid': challenge, 'dummy': random()}, + cookies=True, + imgtype="jpg") + + self.plugin.logDebug("AdsCaptcha result: %s" % result) + + return result diff --git a/module/plugins/captcha/GigasizeCom.py b/module/plugins/captcha/GigasizeCom.py deleted file mode 100644 index 244cf6a2a..000000000 --- a/module/plugins/captcha/GigasizeCom.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.captcha.captcha import OCR - - -class GigasizeCom(OCR): - __name__ = "GigasizeCom" - __type__ = "ocr" - __version__ = "0.10" - - __description__ = """Gigasize.com ocr plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): - self.load_image(image) - self.threshold(2.8) - self.run_tesser(True, False, False, True) - return self.result_captcha diff --git a/module/plugins/captcha/LinksaveIn.py b/module/plugins/captcha/LinksaveIn.py deleted file mode 100644 index de6b0e7ff..000000000 --- a/module/plugins/captcha/LinksaveIn.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- - -try: - from PIL import Image -except ImportError: - import Image - -from glob import glob -from os import sep -from os.path import abspath, dirname - -from module.plugins.captcha.captcha import OCR - - -class LinksaveIn(OCR): - __name__ = "LinksaveIn" - __type__ = "ocr" - __version__ = "0.10" - - __description__ = """Linksave.in ocr plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - def __init__(self): - OCR.__init__(self) - self.data_dir = dirname(abspath(__file__)) + sep + "LinksaveIn" + sep - - - def load_image(self, image): - im = Image.open(image) - frame_nr = 0 - - lut = im.resize((256, 1)) - lut.putdata(range(256)) - lut = list(lut.convert("RGB").getdata()) - - new = Image.new("RGB", im.size) - npix = new.load() - while True: - try: - im.seek(frame_nr) - except EOFError: - break - frame = im.copy() - pix = frame.load() - for x in xrange(frame.size[0]): - for y in xrange(frame.size[1]): - if lut[pix[x, y]] != (0,0,0): - npix[x, y] = lut[pix[x, y]] - frame_nr += 1 - new.save(self.data_dir+"unblacked.png") - self.image = new.copy() - self.pixels = self.image.load() - self.result_captcha = '' - - - def get_bg(self): - stat = {} - cstat = {} - img = self.image.convert("P") - for bgpath in glob(self.data_dir+"bg/*.gif"): - stat[bgpath] = 0 - bg = Image.open(bgpath) - - bglut = bg.resize((256, 1)) - bglut.putdata(range(256)) - bglut = list(bglut.convert("RGB").getdata()) - - lut = img.resize((256, 1)) - lut.putdata(range(256)) - lut = list(lut.convert("RGB").getdata()) - - bgpix = bg.load() - pix = img.load() - for x in xrange(bg.size[0]): - for y in xrange(bg.size[1]): - rgb_bg = bglut[bgpix[x, y]] - rgb_c = lut[pix[x, y]] - try: - cstat[rgb_c] += 1 - except Exception: - cstat[rgb_c] = 1 - if rgb_bg == rgb_c: - stat[bgpath] += 1 - max_p = 0 - bg = "" - for bgpath, value in stat.iteritems(): - if max_p < value: - bg = bgpath - max_p = value - return bg - - - def substract_bg(self, bgpath): - bg = Image.open(bgpath) - img = self.image.convert("P") - - bglut = bg.resize((256, 1)) - bglut.putdata(range(256)) - bglut = list(bglut.convert("RGB").getdata()) - - lut = img.resize((256, 1)) - lut.putdata(range(256)) - lut = list(lut.convert("RGB").getdata()) - - bgpix = bg.load() - pix = img.load() - orgpix = self.image.load() - for x in xrange(bg.size[0]): - for y in xrange(bg.size[1]): - rgb_bg = bglut[bgpix[x, y]] - rgb_c = lut[pix[x, y]] - if rgb_c == rgb_bg: - orgpix[x, y] = (255,255,255) - - - def eval_black_white(self): - new = Image.new("RGB", (140, 75)) - pix = new.load() - orgpix = self.image.load() - thresh = 4 - for x in xrange(new.size[0]): - for y in xrange(new.size[1]): - rgb = orgpix[x, y] - r, g, b = rgb - pix[x, y] = (255,255,255) - if r > max(b, g)+thresh: - pix[x, y] = (0,0,0) - if g < min(r, b): - pix[x, y] = (0,0,0) - if g > max(r, b)+thresh: - pix[x, y] = (0,0,0) - if b > max(r, g)+thresh: - pix[x, y] = (0,0,0) - self.image = new - self.pixels = self.image.load() - - - def get_captcha(self, image): - self.load_image(image) - bg = self.get_bg() - self.substract_bg(bg) - self.eval_black_white() - self.to_greyscale() - self.image.save(self.data_dir+"cleaned_pass1.png") - self.clean(4) - self.clean(4) - self.image.save(self.data_dir+"cleaned_pass2.png") - letters = self.split_captcha_letters() - final = "" - for n, letter in enumerate(letters): - self.image = letter - self.image.save(ocr.data_dir+"letter%d.png" % n) - self.run_tesser(True, True, False, False) - final += self.result_captcha - - return final diff --git a/module/plugins/captcha/NetloadIn.py b/module/plugins/captcha/NetloadIn.py deleted file mode 100644 index 28eb18fb5..000000000 --- a/module/plugins/captcha/NetloadIn.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.captcha.captcha import OCR - - -class NetloadIn(OCR): - __name__ = "NetloadIn" - __type__ = "ocr" - __version__ = "0.10" - - __description__ = """Netload.in ocr plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): - self.load_image(image) - self.to_greyscale() - self.clean(3) - self.clean(3) - self.run_tesser(True, True, False, False) - - self.result_captcha = self.result_captcha.replace(" ", "")[:4] # cut to 4 numbers - - return self.result_captcha diff --git a/module/plugins/captcha/ReCaptcha.py b/module/plugins/captcha/ReCaptcha.py new file mode 100644 index 000000000..4b900c57b --- /dev/null +++ b/module/plugins/captcha/ReCaptcha.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +import re + +from pyload.plugin.Captcha import Captcha + + +class ReCaptcha(Captcha): + __name__ = "ReCaptcha" + __type__ = "captcha" + __version__ = "0.08" + + __description__ = """ReCaptcha captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + KEY_PATTERN = r'recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=([\w-]+)' + KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)' + + + def detect_key(self, html=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("ReCaptcha html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + m = re.search(self.KEY_PATTERN, html) or re.search(self.KEY_AJAX_PATTERN, html) + if m: + self.key = m.group(1).strip() + self.plugin.logDebug("ReCaptcha key: %s" % self.key) + return self.key + else: + self.plugin.logDebug("ReCaptcha key not found") + return None + + + def challenge(self, key=None): + if not key: + if self.detect_key(): + key = self.key + else: + errmsg = _("ReCaptcha key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={'k': key}) + try: + challenge = re.search("challenge : '(.+?)',", html).group(1) + server = re.search("server : '(.+?)',", html).group(1) + except Exception: + errmsg = _("ReCaptcha challenge pattern not found") + self.plugin.error(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("ReCaptcha challenge: %s" % challenge) + + return challenge, self.result(server, challenge) + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha("%simage" % server, + get={'c': challenge}, + cookies=True, + forceUser=True, + imgtype="jpg") + + self.plugin.logDebug("ReCaptcha result: %s" % result) + + return result diff --git a/module/plugins/captcha/ShareonlineBiz.py b/module/plugins/captcha/ShareonlineBiz.py deleted file mode 100644 index 8210e8859..000000000 --- a/module/plugins/captcha/ShareonlineBiz.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.captcha.captcha import OCR - - -class ShareonlineBiz(OCR): - __name__ = "ShareonlineBiz" - __type__ = "ocr" - __version__ = "0.10" - - __description__ = """Shareonline.biz ocr plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] - - - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): - self.load_image(image) - self.to_greyscale() - self.image = self.image.resize((160, 50)) - self.pixels = self.image.load() - self.threshold(1.85) - #self.eval_black_white(240) - #self.derotate_by_average() - - letters = self.split_captcha_letters() - - final = "" - for letter in letters: - self.image = letter - self.run_tesser(True, True, False, False) - final += self.result_captcha - - return final - - #tesseract at 60% diff --git a/module/plugins/captcha/SolveMedia.py b/module/plugins/captcha/SolveMedia.py new file mode 100644 index 000000000..6e2a6c362 --- /dev/null +++ b/module/plugins/captcha/SolveMedia.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +import re + +from pyload.plugin.Captcha import Captcha + + +class SolveMedia(Captcha): + __name__ = "SolveMedia" + __type__ = "captcha" + __version__ = "0.06" + + __description__ = """SolveMedia captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' + + + def challenge(self, key=None): + if not key: + if self.detect_key(): + key = self.key + else: + errmsg = _("SolveMedia key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", get={'k': key}) + try: + challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">', + html).group(1) + server = "http://api.solvemedia.com/papi/media" + except Exception: + errmsg = _("SolveMedia challenge pattern not found") + self.plugin.error(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("SolveMedia challenge: %s" % challenge) + + return challenge, self.result(server, challenge) + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha(server, get={'c': challenge}, imgtype="gif") + + self.plugin.logDebug("SolveMedia result: %s" % result) + + return result diff --git a/module/plugins/captcha/__init__.py b/module/plugins/captcha/__init__.py index e69de29bb..40a96afc6 100644 --- a/module/plugins/captcha/__init__.py +++ b/module/plugins/captcha/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/module/plugins/captcha/captcha.py b/module/plugins/captcha/captcha.py deleted file mode 100644 index 1874ba07d..000000000 --- a/module/plugins/captcha/captcha.py +++ /dev/null @@ -1,319 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -try: - from PIL import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin - -except ImportError: - import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin - -import logging -import os -import subprocess -#import tempfile - -from module.utils import save_join - - -class OCR(object): - __name__ = "OCR" - __type__ = "ocr" - __version__ = "0.11" - - __description__ = """OCR base plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - def __init__(self): - self.logger = logging.getLogger("log") - - - def load_image(self, image): - self.image = Image.open(image) - self.pixels = self.image.load() - self.result_captcha = '' - - - def unload(self): - """delete all tmp images""" - pass - - - def threshold(self, value): - self.image = self.image.point(lambda a: a * value + 10) - - - def run(self, command): - """Run a command""" - - popen = subprocess.Popen(command, bufsize = -1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - popen.wait() - output = popen.stdout.read() +" | "+ popen.stderr.read() - popen.stdout.close() - popen.stderr.close() - self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output)) - - - def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True): - #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") - try: - tmpTif = open(save_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") - tmpTif.close() - - #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") - tmpTxt = open(save_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") - tmpTxt.close() - - except IOError, e: - self.logError(e) - return - - self.logger.debug("save tiff") - self.image.save(tmpTif.name, 'TIFF') - - if os.name == "nt": - tessparams = [os.path.join(pypath, "tesseract", "tesseract.exe")] - else: - tessparams = ["tesseract"] - - tessparams.extend( [os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] ) - - if subset and (digits or lowercase or uppercase): - #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") - with open(save_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub: - tmpSub.write("tessedit_char_whitelist ") - - if digits: - tmpSub.write("0123456789") - if lowercase: - tmpSub.write("abcdefghijklmnopqrstuvwxyz") - if uppercase: - tmpSub.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ") - - tmpSub.write("\n") - tessparams.append("nobatch") - tessparams.append(os.path.abspath(tmpSub.name)) - - self.logger.debug("run tesseract") - self.run(tessparams) - self.logger.debug("read txt") - - try: - with open(tmpTxt.name, 'r') as f: - self.result_captcha = f.read().replace("\n", "") - except Exception: - self.result_captcha = "" - - self.logger.debug(self.result_captcha) - try: - os.remove(tmpTif.name) - os.remove(tmpTxt.name) - if subset and (digits or lowercase or uppercase): - os.remove(tmpSub.name) - except Exception: - pass - - - def get_captcha(self, name): - raise NotImplementedError - - - def to_greyscale(self): - if self.image.mode != 'L': - self.image = self.image.convert('L') - - self.pixels = self.image.load() - - - def eval_black_white(self, limit): - self.pixels = self.image.load() - w, h = self.image.size - for x in xrange(w): - for y in xrange(h): - if self.pixels[x, y] > limit: - self.pixels[x, y] = 255 - else: - self.pixels[x, y] = 0 - - - def clean(self, allowed): - pixels = self.pixels - - w, h = self.image.size - - for x in xrange(w): - for y in xrange(h): - if pixels[x, y] == 255: - continue - # No point in processing white pixels since we only want to remove black pixel - count = 0 - - try: - if pixels[x-1, y-1] != 255: - count += 1 - if pixels[x-1, y] != 255: - count += 1 - if pixels[x-1, y + 1] != 255: - count += 1 - if pixels[x, y + 1] != 255: - count += 1 - if pixels[x + 1, y + 1] != 255: - count += 1 - if pixels[x + 1, y] != 255: - count += 1 - if pixels[x + 1, y-1] != 255: - count += 1 - if pixels[x, y-1] != 255: - count += 1 - except Exception: - pass - - # not enough neighbors are dark pixels so mark this pixel - # to be changed to white - if count < allowed: - pixels[x, y] = 1 - - # second pass: this time set all 1's to 255 (white) - for x in xrange(w): - for y in xrange(h): - if pixels[x, y] == 1: - pixels[x, y] = 255 - - self.pixels = pixels - - - def derotate_by_average(self): - """rotate by checking each angle and guess most suitable""" - - w, h = self.image.size - pixels = self.pixels - - for x in xrange(w): - for y in xrange(h): - if pixels[x, y] == 0: - pixels[x, y] = 155 - - highest = {} - counts = {} - - for angle in xrange(-45, 45): - - tmpimage = self.image.rotate(angle) - - pixels = tmpimage.load() - - w, h = self.image.size - - for x in xrange(w): - for y in xrange(h): - if pixels[x, y] == 0: - pixels[x, y] = 255 - - - count = {} - - for x in xrange(w): - count[x] = 0 - for y in xrange(h): - if pixels[x, y] == 155: - count[x] += 1 - - sum = 0 - cnt = 0 - - for x in count.values(): - if x != 0: - sum += x - cnt += 1 - - avg = sum / cnt - counts[angle] = cnt - highest[angle] = 0 - for x in count.values(): - if x > highest[angle]: - highest[angle] = x - - highest[angle] = highest[angle] - avg - - hkey = 0 - hvalue = 0 - - for key, value in highest.iteritems(): - if value > hvalue: - hkey = key - hvalue = value - - self.image = self.image.rotate(hkey) - pixels = self.image.load() - - for x in xrange(w): - for y in xrange(h): - if pixels[x, y] == 0: - pixels[x, y] = 255 - - if pixels[x, y] == 155: - pixels[x, y] = 0 - - self.pixels = pixels - - - def split_captcha_letters(self): - captcha = self.image - started = False - letters = [] - width, height = captcha.size - bottomY, topY = 0, height - pixels = captcha.load() - - for x in xrange(width): - black_pixel_in_col = False - for y in xrange(height): - if pixels[x, y] != 255: - if not started: - started = True - firstX = x - lastX = x - - if y > bottomY: - bottomY = y - if y < topY: - topY = y - if x > lastX: - lastX = x - - black_pixel_in_col = True - - if black_pixel_in_col is False and started is True: - rect = (firstX, topY, lastX, bottomY) - new_captcha = captcha.crop(rect) - - w, h = new_captcha.size - if w > 5 and h > 5: - letters.append(new_captcha) - - started = False - bottomY, topY = 0, height - - return letters - - - def correct(self, values, var=None): - if var: - result = var - else: - result = self.result_captcha - - for key, item in values.iteritems(): - - if key.__class__ == str: - result = result.replace(key, item) - else: - for expr in key: - result = result.replace(expr, item) - - if var: - return result - else: - self.result_captcha = result |