Pirater reCAPTCHA v2

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

  1. Position du bouton de recherche





  2. Simulation du mouvement de la souris aux coordonnées du bouton "Je ne suis pas un robot"





  3. Imitation d'appuyer sur le bouton "Je ne suis pas un robot"





  4. Recevoir une image (du serveur Google, envoyée intacte)





  5. Obtenir la classe de l'objet que vous recherchez (à partir de html)





  6. Obtenir les coordonnées de cellule (à partir de HTML)





  7. Décision





  8. Activation cellulaire basée sur la solution





  9. Appuyer sur Terminé / Suivant / Confirmer





  10. 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.








All Articles