Совсем недавно открылся портал Единого государственного реестра сайтов. Отдельно от всего прочего мне приглянулась очень слабая каптча, и я решил её побороть.
Подобными вещами я уже занимался, правда, не в таком масштабе. Если вам интересно, как получить КПД распознавания в 57% используя только GNU/Bash, imagemagick и Tesseract-ocr, добро пожаловать под кат.
Нижеследующая инструкция может быть легко модифицирована под любые другие подобные слабые каптчи.
Вступление
Распознавание самих картинок каптч можно разделить ровно на два этапа:
- Подготовка картинки. Для этого я буду использовать imagemagick
- Распознавание символов. В этом случае я выбрал Tesseract, но на более простых каптчах (без поворотов, без разрывов) можно использовать ocrad, к примеру.
Получение картинок и отправление результатов легко совершается при помощи curl (или wget, но с ним я не подружился).
Подготовка картинок
В ImageMagick есть встроенный язык Fx для создания спец-эффектов. Так как на каптче реестра буквы всегда черные, самый простой вариант скрипта, убирающий всё нечерное, будет выглядеть так:
convert file.png -colorspace cmyk -fx 'k * (k >= 1.0)' file.ppm
Выполнение занимает десятую секунды, что допустимо. Но качество картинки — нет, так что нужно пройтись по ней еще раз. Можно положиться на то, что если буква была задета линией, то в таком месте должны быть закрашенные пиксели-соседи сразу с двух противоположных сторон:
convert file.ppm -colorspace cmyk -fx 'k || (p[-1].k && p[+1].k) || (p[0,-1].k && p[0,+1].k)' out.ppm
Чем мы жертвуем еще половиной секунды. Как окажется позже, это увеличит процент успеха с 1% до 22% (на 100 контрольных картинках).
Распознавание символов
Тут всё еще проще. Травим tesseract на картинку, забираем результат из файла. При желании, можно научить его шрифту каптчи как отдельному языку, но овчинка выделки не стоит.
tesseract out.ppm result -psm 8 nobatch digits 2>/dev/null
res=$(cat result.txt | sed -e 's/[^0-9]//g')
Отработка в реальных условиях
Как я уже сказал выше, такая комбинация дала правильный ответ на 22 из 100 тестовых картинок. Но тесты — не интересно, и я решил проверить скорость работы в реальных условиях.
#!/bin/bash
c=$(curl -c cook.txt http://zapret-info.gov.ru/ | iconv -f cp1251 | grep capcha | sed -e 's/"/n/g' | grep services)
url="http://zapret-info.gov.ru$c"
r=work01
#get
curl -b cook.txt "$url" > "$r.png"
#prepare
convert $r.png -colorspace cmyk -fx 'k * (k >= 1.0)' $r.png
convert $r.png -colorspace cmyk -fx 'k || (p[-1].k && p[+1].k) || (p[0,-1].k && p[0,+1].k)' $r.png
#exterminate
tesseract $r.png $r -psm 8 nobatch digits
res=`cat $r.txt | sed -e 's/[^0-9]//g'`
#check
if [ "$(echo $res | wc -c)" -ne 9 ]; then
echo fail && exit
fi
#send
code=$(echo $c | sed -e 's/[^0-9]//g')
fin=`curl -b cook.txt -d "act=search&secretcodeId=$code&searchstring=ya.ru&secretcodestatus=$res" 'http://zapret-info.gov.ru/'| iconv -f cp1251`
if echo "$fin" | grep -q 'не значится'; then
echo succ
else
echo tesfail
fi
rm $r.png $r.txt cook.txt
#!/bin/bash
score=0
all=0
while [ "$score" -lt 41 ]; do
r=`bash per.sh 2>/dev/null`
[ "$r" = 'succ' ] && let score++
let all++
echo "$score/$all; $r"
done
time bash tt.sh | tee -a log.txt
Результаты, статистика
Вышеуказанный набор скриптов производит 41 успешную проверку на наличие ya.ru в реестре. Небольшая статистика по нему:
Успешно подобрано: 41
Всего каптч: 218
Время работы: 5 минут 4 секунды (5m4.178s)
КПД: 19%
КПД с учетом заведомо неправильных решений, которые не отправлялись на проверку: 57%
Максимальное КПД во время работы: 33%
Минимальное КПД во время работы: 12%
Пути улучшения
- Одну картинку можно получить множество раз, получая разные каптчи с одним текстом. Это можно использовать.
- Используя нормальные и проверенные способы можно получить очень хороший КПД.
- Или просто научить Tesseract шрифту каптчи. Сам шрифт похож на Arial, но тессеракт постоянно путает 3 и 8, 1 и 7.
- Оптимизировать получение информации: значительная часть времени работы скрипта уходит на получение страниц и картинок с сервера.
Автор: tyderh