Vous n'êtes pas identifié(e).
hello
bon, devant mon échec cuisant à bypasser le système de captcha du forum (pour l'instant niark niark niark), je suis allé me défouler ailleurs .. sur une captcha image pour changer !
la bête se trouve ici => http://demo.visualcaptcha.net/
et histoire de changer encore un peu (le changement c'est toujours bon), je me suis dis que j'allais utiliser, non pas un réseau de neurones supervisé, mais une machine à vecteur de support (AKA SVM)..
kezako me direz-vous ??
grosso modo, ca cherche le meilleur hyperplan pour séparer les données
page avec schéma bien parlant => https://www.igvita.com/2008/01/07/suppo … m-in-ruby/
pari réussi .. j'ai dû mettre 3-4 heures en tout (en trois fois) et ce matin, j'ai bouclé le bouzin .. et je vous donne l'intégralité du code (sympa hein !)
un module ruby, trois classes,
- une pour scraper les images et se faire sa BDD
- une pour entrainer le SVM
- et la dernière pour test grandeur nature (connexion à la page, récup du mot à trouver, scrape et analyse des images, et click sur les boutons qui vont bien)
require 'time'
require 'date'
require 'fileutils'
require 'open-uri'
require 'headless'
require 'selenium/webdriver'
require 'watir-webdriver'
require 'watir-get-image-content'
require 'RMagick'
require 'chunky_png'
require 'cgi'
require 'libsvm'
module Decode_Visual_Captcha
class ScrapePicto
START_URL = "http://demo.visualcaptcha.net/"
def initialize
make_agent
end
def finalize
kill
end
def aleat
r = Random.new
return r.rand(15..75)
end
def parse_request(string)
out = []
params = CGI.parse(string)
params.each_pair do |key,value|
out << value
end
return out.join
end
def click_refresh
@b.image(:src => "img/refresh.png").click
end
def get_word
label = @b.p(:class => "visualCaptcha-explanation").strong.text
return label
end
def save_img index, label, img_dest,img_src
new_nm = "images/" << label << "_" << img_dest << "_" << index << ".png"
begin
image = img_src.to_png_base64
File.open(new_nm, 'wb') do |file|
file.write(Base64.decode64(image))
end
rescue Exception => e
puts e.message
end
end
def parse_page label
begin
@b.divs(:class =>"img").each do |img|
index = img.img.attribute_value('data-index')
nm = parse_request(img.img.src)
save_img index, label, nm, img.img
end
rescue Exception => e
puts e.message
end
return true
end
def run
begin
@b.goto START_URL
sleep 3
100.times do
puts "hop"
label = get_word
parse_page label
click_refresh
sleep 3
end
rescue Exception => e
#puts e.message
ensure
finalize
end
return true
end
=begin doc
partie private
=end
private
def make_agent
@headless = Headless.new
@headless.start
Selenium::WebDriver::Firefox.path = '/home/digital/firefox31/firefox/firefox'
@b = Watir::Browser.new :firefox
end
def kill
@b.close
@headless.destroy
end
end
###############################
###############################
class TestSvm
START_URL = "http://demo.visualcaptcha.net/"
def initialize
make_agent
end
def finalize
kill
end
def parse_request(string)
out = []
params = CGI.parse(string)
params.each_pair do |key,value|
out << value
end
return out.join
end
def parse_nm string
tab = string.split(".")
tmp_tab = tab[0].split("_")
index = tmp_tab[2]
return index
end
def split_name string
res = string.split("_")
label = res[0]
return label
end
def click_refresh
@b.image(:src => "img/refresh.png").click
end
def click my_index
begin
@b.divs(:class =>"img").each do |img|
index = img.img.attribute_value('data-index')
if index == my_index
then
img.click
end
end
@b.button(:name => "submit-bt").click
sleep 3
rescue Exception => e
puts e.message
end
end
def get_word
label = @b.p(:class => "visualCaptcha-explanation").strong.text
return label
end
def save_img index, label, img_dest,img_src
new_nm = "work_svm/" << label << "_" << img_dest << "_" << index << ".png"
begin
image = img_src.to_png_base64
File.open(new_nm, 'wb') do |file|
file.write(Base64.decode64(image))
end
rescue Exception => e
puts e.message
end
end
def check
ls = []
Dir['train_svm/*.png'].each do |file|
obj = split_name File.basename(file)
ls << obj
end
return ls.uniq
end
def vector(img)
out = []
image = Magick::Image.read(img).first
image.each_pixel do |pixel, c, r|
out << (pixel.intensity > 0 ? 1 : 0)
end
return out
end
def resolve_captcha label
words = check
ind = []
model = Libsvm::Model.load("visual_captcha.svm")
Dir['work_svm/*.png'].each do |file|
input = vector(file)
index = parse_nm File.basename(file)
pred = model.predict(Libsvm::Node.features(input))
if
label == words[pred]
then
ind = index
end
end
return ind
end
def parse_page label
begin
@b.divs(:class =>"img").each do |img|
index = img.img.attribute_value('data-index')
nm = parse_request(img.img.src)
save_img index, label, nm, img.img
end
rescue Exception => e
puts e.message
end
return true
end
def run
begin
@b.goto START_URL
sleep 3
1.times do
label = get_word
parse_page label
res = resolve_captcha label
click res
end
rescue Exception => e
#puts e.message
ensure
finalize
end
return true
end
=begin doc
partie private
=end
private
def make_agent
#@headless = Headless.new
#@headless.start
Selenium::WebDriver::Firefox.path = '/home/digital/firefox31/firefox/firefox'
@b = Watir::Browser.new :firefox
end
def kill
@b.close
#@headless.destroy
end
end
###############################
###############################
class TrainSvm
=begin doc
partie image
=end
def split_name string
res = string.split("_")
label = res[0]
return label
end
def vector(img)
out = []
image = Magick::Image.read(img).first
image.each_pixel do |pixel, c, r|
out << (pixel.intensity > 0 ? 1 : 0)
end
return out
end
def check
ls = []
Dir['train_svm/*.png'].each do |file|
obj = split_name File.basename(file)
ls << obj
end
return ls.uniq
end
def normalize vec
s = Math.sqrt(vec.map{|x|x*x}.inject{|x,y|x+y})
vec.map{|x| x/s}
end
=begin doc
partie SOM
=end
def som
alpha = ('a'..'z').to_a + ('0'..'9').to_a
example_test = []
captcha_out = []
Dir['images/*.png'].each do |file|
vec = vector(file)
obj = split_name File.basename(file)
end
end
=begin doc
partie SVM
=end
def svm words
alphahash = Hash[words.map.with_index.to_a] # "a"=>0,"b"=>1,"c"=>2 ..
puts alphahash
examples, outputs = [], []
=begin doc
partie train
=end
problem = Libsvm::Problem.new
parameter = Libsvm::SvmParameter.new
parameter.cache_size = 1 # in megabytes
parameter.eps = 0.001
parameter.c = 10
Dir['train_svm/*.png'].each do |file|
vec = vector(file)
obj = split_name File.basename(file)
examples << vec.flatten
outputs << alphahash[obj]
end
vectors = examples.map {|ary| Libsvm::Node.features(ary) }
labels = outputs
problem.set_examples(labels, vectors)
model = Libsvm::Model.train(problem, parameter)
=begin doc
partie test
=end
Dir['test_svm/*.png'].each do |file|
input = vector(file)
obj = split_name File.basename(file)
pred = model.predict(Libsvm::Node.features(input))
puts "#{obj} : Predicted #{words[pred]}"
end
model.save("visual_captcha.svm")
end
end
end
def main_test
include Decode_Visual_Captcha
bot = TestSvm.new
bot.run
end
def main_vector
include Decode_Visual_Captcha
bot = TrainSvm.new
words = bot.check
bot.svm words
end
def main_scrap
include Decode_Visual_Captcha
bot = ScrapePicto.new
bot.run
end
def main
#main_scrap
#main_vector
#main_test
end
main
enjoy
edit :
à noter plusieurs choses :
- le code est fait à l'arrache, ya surement moyen d'optimiser le tout
- le SVM peut servir à catégoriser du texte, dans le lien que j'ai filé, ils s'en servent pour la détection du spam
c'est tout je crois
Dernière modification par conquering_lion (2014-11-29 12:41:14)
🔴 Hors ligne
hello
non non, du tout, c'est plus le challenge technique qui m'amuse
au pire je pourrais toujours fourrer tous mes tests dans un mémoire de doctorat en IA un de ces 4, du style "les captchas ne seront jamais sures"
pour ce test, le coté intéressant était de voir le comportement d'un SVM (que je n'avais jamais utilisé avant, et à peine vu en cours de fac) sur de l'image .. deux nouveautés pour moi
je pense que je vais tester les captchas sous forme de petits jeux où il faut replacer correctement les éléments mouvants .. ca peut être pas mal
edit :
c'est aussi un plaisir de coder en ruby, donc doublement sympa
Dernière modification par conquering_lion (2014-12-01 19:32:26)
🔴 Hors ligne
C'est sur que ce genre de challenge est toujours sympa !
Je dis ça parce que ton captcha solver audio, ça pourrait vraiment être une tuerie si on pouvait se câbler dessus !
Pour moi ce genre de dev, ça vaut mieux que juste de l'amusement
🔴 Hors ligne
🔴 Hors ligne