Un jeu ennuyeux - balisage de données pour Google. Si vous collectez des informations disponibles à partir de ressources qui ne vous appartiennent pas, et que vous n'avez pas réussi à mettre en place une solution pour surmonter cet obstacle, les conseils d'un développeur novice vous aideront. Je décrirai l'une des méthodes, basée sur un détecteur d'objet, se débrouille bien avec le type 4x4, pire avec le 3x3. En utilisant l'architecture YOLO, sweet spot précision / performance, l'approche est la même pour tous les détecteurs. Dans un produit commercial, il vaut la peine d'utiliser un «ensemble» de réseaux neuronaux, en ajoutant la classification de chaque cellule au détecteur, cela augmentera la précision globale avec des performances acceptables. En outre, ce problème peut être résolu en utilisant l'apprentissage par renforcement A2C / DQN ou toute architecture moderne, transformateurs, réseaux antagonistes génératifs.
Algorithme approximatif
Position du bouton de recherche
Simulation du mouvement de la souris aux coordonnées du bouton "Je ne suis pas un robot"
Imitation d'appuyer sur le bouton "Je ne suis pas un robot"
Recevoir une image (du serveur Google, envoyée intacte)
Obtenir la classe de l'objet que vous recherchez (à partir de html)
Obtenir les coordonnées de cellule (à partir de HTML)
Décision
Activation cellulaire basée sur la solution
Appuyer sur Terminé / Suivant / Confirmer
Traiter
Si reCaptcha continue, répétez de 4 à 10.
Outils utiles en Python
pynput
sélénium
engourdi
tensorflow
ouvrir
scipy
belle soupe, vous pouvez vous en tirer avec un sélénium
Le code a été trouvé dans l'immensité de mon réseau de neurones, ce qui signifie que j'ai vu quelque chose sur Internet, je ne vis pas dans le vide
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from pynput.mouse import Button, Controller
import scipy.interpolate as si
import numpy as np
import cv2
import time
import random
import os
import io
import base64
# B-
def human_like_mouse_move(action, start_element):
points = [[6, 2], [3, 2],[0, 0], [0, 2]];
points = np.array(points)
x = points[:,0]
y = points[:,1]
t = range(len(points))
ipl_t = np.linspace(0.0, len(points) - 1, 100)
x_tup = si.splrep(t, x, k=1)
y_tup = si.splrep(t, y, k=1)
x_list = list(x_tup)
xl = x.tolist()
x_list[1] = xl + [0.0, 0.0, 0.0, 0.0]
y_list = list(y_tup)
yl = y.tolist()
y_list[1] = yl + [0.0, 0.0, 0.0, 0.0]
x_i = si.splev(ipl_t, x_list)
y_i = si.splev(ipl_t, y_list)
startElement = start_element
action.move_to_element(startElement);
action.perform();
c = 5
i = 0
for mouse_x, mouse_y in zip(x_i, y_i):
action.move_by_offset(mouse_x,mouse_y);
action.perform();
print("Move mouse to, %s ,%s" % (mouse_x, mouse_y))
i += 1
if i == c:
break;
# "" selenium
def my_proxy(PROXY_HOST,PROXY_PORT):
fp = webdriver.FirefoxProfile()
fp.set_preference("network.proxy.type", 1)
fp.set_preference("network.proxy.socks",PROXY_HOST)
fp.set_preference("network.proxy.socks_port",int(PROXY_PORT))
fp.update_preferences()
options = Options()
options.headless = True #
return webdriver.Firefox(executable_path="geckodriver/geckodriver", options=options, firefox_profile=fp)
# tor , reCaptcha ,
#
proxy = my_proxy("127.0.0.1", 9050)
proxy.get("https://www.google.com/search?q=apple")
Après la demande, pour de nombreuses raisons compréhensibles, un reCaptcha apparaît.
# reCaptcha iframe's
# iframe №1
proxy.switch_to.frame(proxy.find_elements_by_tag_name("iframe")[0])
# " "
check_box = WebDriverWait(proxy, 10).until(EC.element_to_be_clickable((By.ID ,"recaptcha-anchor")))
time.sleep(2)
# "
action = ActionChains(proxy);
human_like_mouse_move(action, check_box)
check_box.click()
time.sleep(2)
Nous obtenons des informations pour un traitement ultérieur: lien vers l'image, classe de recherche, type reCaptcha.
# iframe №2
proxy.switch_to.default_content()
iframes = proxy.find_elements_by_tag_name("iframe")
proxy.switch_to.frame(iframes[2])
html = proxy.page_source
# , reCaptcha
try:
img_rc = proxy.find_elements_by_xpath('//img[@class="rc-image-tile-33"]')[0]
t_type = 3
except IndexError:
img_rc = proxy.find_elements_by_xpath('//img[@class="rc-image-tile-44"]')[0]
t_type = 4
#
try:
required_class = proxy.find_elements_by_xpath('//div[@class="rc-imageselect-desc-no-canonical"]/strong')[0].text
except IndexError:
required_class = proxy.find_elements_by_xpath('//div[@class="rc-imageselect-desc"]/strong')[0].text
time.sleep(2)
, " ". javascript, XMLHttpRequest, canvas, python base64. base64, numpy array. , https://habr.com/ru/post/449236/
answ = proxy.execute_script('''
var img = new Image();
var cnv = document.createElement('canvas');
cnv.id = 'tutorial';
img.onload = function(){
cnv.height = img.height;
cnv.width = img.width;
console.log(cnv.width, cnv.height, img.width, img.height);
cnv.getContext('2d').drawImage(img, 0, 0);
}
var request = new XMLHttpRequest();
request.open('GET', arguments[0].src);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
img.src = e.target.result;
};
};
request.send();
var child = document.body.appendChild(cnv);
''', img_rc)
time.sleep(4)
answ = proxy.execute_script('''
cnv = document.getElementById('tutorial');
return cnv.toDataURL('image/jpeg').substring(22);
''')
nparr = np.asarray(bytearray(io.BytesIO(base64.b64decode(answ)).read()), dtype=np.uint8)
img_np = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
, : " ". YOLO , .
def draw_boxes(image, boxes, scores, labels, classes, detection_size, search_class):
"""
:param boxes, shape of [num, 4]
:param scores, shape of [num, ]
:param labels, shape of [num, ]
:param image,
:param classes, the return list from the function `read_coco_names`
"""
new = np.ones(shape=image.shape, dtype=np.float32)
ans = []
if boxes is None:
return ans, image, new
for i in range(len(labels)): # for each bounding box, do:
bbox, score, label = boxes[i], scores[i], classes[labels[i]]
bbox_text = "%s %.2f" %(label, score)
# convert_to_original_size
detection_size, original_size = np.array(detection_size), np.array(image.shape[1])
ratio = float(original_size) / float(detection_size)
bbox = list((bbox.reshape(2,2) * ratio).reshape(-1))
coord = [abs(int(x)) for x in bbox]
#
o0 = coord[0]
o1 = coord[1]
o2 = coord[2]
o3 = coord[3]
#
if search_class == label.split('\n')[0]:
new[o1:o3, o0:o2, :] = 2
ans.append(classes[labels[i]])
return ans, image, new
#
def imcr(i, col, activation_threshold = 1):
answ = []
im_w, im_h, im_c = i.shape
w, h = im_w//col, im_h//col
sZero = i[0:w, 0:h,:].size
num = 0
for wi in range(0, col):
for hi in range(0, col):
num += 1
P_R = (np.sum(i[wi*w:(wi+1)*w, hi*h:(hi+1)*h, :]) / sZero) * 100
P_R = P_R - 100
if activation_threshold < int(P_R):
answ.append(num)
else:
pass
return answ
def ocr(img_np, required_class, t_type):
# img_np -> YOLO -> B,C
#
boxes, scores, labels = cpu_nms(B, C, len(classes), max_boxes=1000, score_thresh=0.4, iou_thresh=0.5)
#
result, img, z_image = draw_boxes(img_np, boxes, scores, labels, classes, yolo_image_shape, required_class)
#
answ = imcr(np.array(z_image), t_type)
, imcr(image_array, type_captcha, activation_threshold) - ,
:
image_array -
type_captcha - , 4 (4x4)
activation_threshold - , 1%
:
, , .
answ_ocr = ocr(img_np, required_class, t_type)
ids = proxy.find_elements_by_xpath('//td[@class="rc-imageselect-tile"]')
for i in answ_ocr:
ids[i].click()
#
confirm_btn = WebDriverWait(proxy, 4).until(EC.element_to_be_clickable((By.XPATH ,'//button[@id="recaptcha-verify-button"]'))) #
action = ActionChains(proxy);
human_like_mouse_move(action, confirm_btn) #
confirm_btn.click() #
Ce n'est pas un didacticiel détaillé, mais des astuces avec des extraits de code. Si nous appliquons l'approche proposée, avec d'autres algorithmes, la précision est de 93% et plus. À l'aide d'un détecteur, votre tâche principale est d'améliorer la précision du détecteur (YOLO, RCNN, SSD). En outre, l'une des conditions pour réussir le contournement de google captcha est l'utilisation de "proxies propres". Je ne suis pas particulièrement doué pour convertir mes pensées en texte, j'espère que la tentative réussira et mon article apparaîtra sur cette ressource.