Skip to content

Instantly share code, notes, and snippets.

@kalinochkind
Created August 19, 2021 22:41
Show Gist options
  • Save kalinochkind/78c7db4917ad74b2153407ab17f6ba9c to your computer and use it in GitHub Desktop.
Save kalinochkind/78c7db4917ad74b2153407ab17f6ba9c to your computer and use it in GitHub Desktop.
Captcha bot
from flask import Flask, escape, request
from werkzeug.contrib.fixers import ProxyFix
from PIL import Image, ImageDraw, ImageFont, ImageChops
import numpy as np
import io
import cairosvg
app = Flask(__name__)
@app.route('/solvecaptcha', methods=['POST'])
def hello():
data = request.get_data()
return get_label(data)
def get_pos(coord):
if 12 <= coord <= 24:
return 1
elif 45 <= coord <= 57:
return 2
elif 78 <= coord <= 90:
return 3
elif 112 <= coord <= 123:
return 4
elif 146 <= coord <= 156:
return 5
def preprocess_image(img):
arr = np.array(img.convert('HSV'))
brr = None
DX, DY = 5, 1
for ix in range(DX):
for iy in range(DY):
nrr = arr[ix:(ix-DX+1 or None), iy:(iy-DY+1 or None), 2]
if brr is not None:
brr = np.minimum(brr, nrr)
else:
brr = nrr
brr = ((brr > 131) * 255).astype(np.uint8)
return Image.fromarray(brr).resize((200, 48)).convert('1')
font = ImageFont.truetype('./Roboto.ttf', encoding='unic', size=50)
letters = {}
def get_letter(letter, offset):
if (letter, offset) not in letters:
my = Image.new('L', (200, 48))
draw = ImageDraw.Draw(my)
draw.text((offset, -6), letter, fill='white', font=font)
letters[(letter, offset)] = my.convert('1')
return letters[(letter, offset)]
def get_label(data):
png = io.BytesIO()
cairosvg.svg2png(data, write_to=png)
img = preprocess_image(Image.open(png))
# img.save('/var/www/captcha_bot/test.png')
last_pos = None
found = {}
for i in range(160):
pos = get_pos(i)
if pos is None:
continue
if last_pos is None or pos != last_pos:
if last_pos is not None:
img = found[last_pos][2]
last_pos = pos
for c in 'абвгдежзийклмнопстхшя':
my = get_letter(c, i)
res = ImageChops.logical_xor(my, img)
diff = np.sum(res)
if pos not in found or diff > found[pos][1]:
found[pos] = (c, diff, res)
# found[5][2].save('/var/www/captcha_bot/test2.png')
return ''.join(found[i][0] for i in [1, 2, 3, 4, 5])
app.wsgi_app = ProxyFix(app.wsgi_app)
if __name__ == "__main__":
print('RUNNING')
app.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment