Форум сайта python.su
Доброго вам времени суток. Столкнулся с необходимостью обойти капчу на сайте. Знаю, что есть вариант её просто отключить для определенного адреса, но суть задачи как раз именно в этом. Так вот, перерыл кучу страничек в поисках информации. Нашёл несколько интересных вариантов, но не совсем могу понять как они работают. Теперь немного подробностей:
Вот так выглядит сама капча (captcha.jpg во вложении) вариант с распознаванием картинки с помощью извлечения цвета, как я понимаю, не подходит, т.к. не получится выделить именно цвет символов. (или получится?), поэтому изучал дальше и нашёл еще один похожий вариант, но никак не могу разобраться в связи с небольшим багажом знаний языка Python.
Тем, кто задавался этим вопросом, думаю. будет знаком вот такой вот декодер:
from PIL import Image
import sys
def decoder(
im,
threshold=200,
mask=“letters.bmp”,
alphabet=“0123456789abcdef”):
img = Image.open(im)
img = img.convert(“RGB”)
box = (8, 8, 58, 18)
img = img.crop(box)
pixdata = img.load()
# open the mask
letters = Image.open(mask)
ledata = letters.load()
def test_letter(img, letter):
A = img.load()
B = letter.load()
mx = 1000000
max_x = 0
x = 0
for x in range(img.size - letter.size):
_sum = 0
for i in range(letter.size):
for j in range(letter.size):
_sum = _sum + abs(A - B)
if _sum < mx:
mx = _sum
max_x = x
return mx, max_x
# Clean the background noise, if color != white, then set to black.
for y in range(img.size):
for x in range(img.size):
if (pixdata > threshold) \
and (pixdata > threshold) \
and (pixdata > threshold):
pixdata = (255, 255, 255, 255)
else:
pixdata = (0, 0, 0, 255)
counter = 0
old_x = -1
letterlist =
for x in range(letters.size):
black = True
for y in range(letters.size):
if ledata != 0:
black = False
break
if black:
box = (old_x + 1, 0, x, 10)
letter = letters.crop(box)
t = test_letter(img, letter)
letterlist.append((t, alphabet, t))
old_x = x
counter += 1
box = (old_x + 1, 0, 140, 10)
letter = letters.crop(box)
t = test_letter(img, letter)
letterlist.append((t, alphabet, t))
t = sorted(letterlist)
t = t # 5-letter captcha
final = sorted(t, key=lambda e: e)
answer = ''.join(map(lambda l: l, final))
return answer
if __name__ == ‘__main__’:
print(decoder(sys.argv))
Вызывается он в другом файле, который выглядит так:
import unittest
from captcha_decoder import decoder
class TestStringMethods(unittest.TestCase):
def test_images(self):
self.assertEqual(decoder('test.jpg'), ‘c71fe’)
self.assertEqual(decoder('test2.jpg'), ‘7f4ca’)
if __name__ == ‘__main__’:
unittest.main()
Собственно, сам вопрос. Во втором файлике в строке self.assertEqual(decoder('test.jpg'), ‘c71fe’) указана картинка и символы, которые на ней изображены. При запуске в среде разработки PyCharm, получаем “ок” т.е. как я понимаю, указанные символы соответствуют символам на изображении. А как мне выделить то сами символы? т.е. не сверить, что они соответствуют, а именно узнать, какие там символы с помощью этого замечательного декодера. Извиняюсь за неграмотность задаваемого вопроса, но я надеюсь, что вы сможете понять, что я хотел бы найти. Заранее спасибо. Очень надеюсь на вашу помощь.
Прикреплённый файлы: captcha.jpg (5,1 KБ)
Офлайн
Возвращаемые символы - это переменная answer. Что мешает ее просто распечатать?
И вставляйте код с помощью тега code, чтобы отступы сохранялись.
Офлайн
Elaphe
Возвращаемые символы - это переменная answer. Что мешает ее просто распечатать?И вставляйте код с помощью тега code, чтобы отступы сохранялись.
from PIL import Image import sys def decoder( im, threshold=200, mask="letters.bmp", alphabet="0123456789abcdef"): img = Image.open(im) img = img.convert("RGB") box = (8, 8, 58, 18) img = img.crop(box) pixdata = img.load() # open the mask letters = Image.open(mask) ledata = letters.load() def test_letter(img, letter): A = img.load() B = letter.load() mx = 1000000 max_x = 0 x = 0 for x in range(img.size[0] - letter.size[0]): _sum = 0 for i in range(letter.size[0]): for j in range(letter.size[1]): _sum = _sum + abs(A[x + i, j][0] - B[i, j][0]) if _sum < mx: mx = _sum max_x = x return mx, max_x # Clean the background noise, if color != white, then set to black. for y in range(img.size[1]): for x in range(img.size[0]): if (pixdata[x, y][0] > threshold) \ and (pixdata[x, y][1] > threshold) \ and (pixdata[x, y][2] > threshold): pixdata[x, y] = (255, 255, 255, 255) else: pixdata[x, y] = (0, 0, 0, 255) counter = 0 old_x = -1 letterlist = [] for x in range(letters.size[0]): black = True for y in range(letters.size[1]): if ledata[x, y][0] != 0: black = False break if black: box = (old_x + 1, 0, x, 10) letter = letters.crop(box) t = test_letter(img, letter) letterlist.append((t[0], alphabet[counter], t[1])) old_x = x counter += 1 box = (old_x + 1, 0, 140, 10) letter = letters.crop(box) t = test_letter(img, letter) letterlist.append((t[0], alphabet[counter], t[1])) t = sorted(letterlist) t = t[0:5] # 5-letter captcha final = sorted(t, key=lambda e: e[2]) answer = ''.join(map(lambda l: l[1], final)) return answer if __name__ == '__main__': print(decoder(sys.argv[1]))
import unittest from captcha_decoder import decoder class TestStringMethods(unittest.TestCase): def test_images(self): self.assertEqual(decoder('test.jpg'), 'c71fe') self.assertEqual(decoder('test2.jpg'), '7f4ca') if __name__ == '__main__': unittest.main()
Офлайн
Написано же - не хватает скобок.
Надо вот так:
print(answer)
Офлайн