'CAPTCHA'를 돌파하는 서비스 '2Captcha'와 Ruby+Chrome_Remote로 자동 스크래핑

소개



스크래핑하고 있으면, CAPTCHA가 나와 프로그램이 멈춘 경험, 있다고 생각합니다.
(그런 분 밖에 이 기사는 보지 않습니다.)
어떻게든 CAPTHCA를 회피하기 위해서, BOT같지 않은 움직임을 시키거나, IP 분산이라고 하는 손도 있습니다만, 이번은 솔직하게 CAPTCHA를 풀어 주려고 합니다.
물론, 엔지니어이므로 자신의 손으로 풀기보다는 프로그램상에서 자동으로 풀어주고 싶네요.
기계 학습은 학습 비용과 도입 비용이 높고 더 즐겁게하고 싶습니다.
2Cpathca라는 서비스가 그것을 실현합니다.
그 밖에도 다양한 서비스가 있으므로, 자신에게 있던 것을 찾아 주세요.
파이썬 기사 는 있었지만, Ruby의 기사는 발견되지 않았기 때문에 썼습니다.

2Capthca란?




CAPTHCA 기능을 돌파하는 서비스로 API를 이용하여 인증을 자동화할 수 있습니다.
유료 서비스입니다만, reCAPTCHA v2라면 1,000 리퀘스트로 $2.99로 저렴합니다.
만약을 위해 거절을 넣어 둡니다만, 나와 2Captcha의 사이에 판촉등에서의 금전의 교환은 없습니다.

Chrome_Remote란?



Chrome의 인스턴스를 Ruby에서 조작할 수 있는 라이브러리입니다.
자세한 사용법은 설명 페이지리포지토리을 참조하십시오.
스크래핑하는 전제로서, 처음에는 CAPTHCA가 나오기 어려운 방식으로 해야 합니다.
Selenium 등과 달리 Chrome을 그대로 움직이는 Chrome_Remote 쪽이 BOT 판정되기 어렵다고 생각합니다. (그중 차이를 검증하고 싶다.)

하고 싶은 일




reCAPTCHA 데모 페이지 돌파합니다.
2Capthca 계정을 만들거나 api 키를 얻으려면 선인의 기사을 참조하십시오.

'2Captcha'와 Ruby + Chrome_Remote로 reCAPTHCA를 돌파



2Captcha의 api 키를 얻고 파일을 저장합니다.



key.yaml
---
:2Capthca: 2Captchaのapiキー

Chrome을 debugging-port로 시작합니다.



Mac의 경우
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 &

필요한 Gem을 설치하십시오.



Gemfile
source "https://rubygems.org"
gem 'nokogiri'
gem 'chrome_remote'
bundle install

루비 프로그램 본체입니다.



crawler.rb

require 'nokogiri'
require 'chrome_remote'
require 'yaml'

class CaptchaDetectedException < StandardError; end

class ChromeController
  def initialize
    @chrome = ChromeRemote.client

    # Enable events
    @chrome.send_cmd "Network.enable"
    @chrome.send_cmd "Page.enable"
  end

  def open(url)
    # ページアクセス
    move_to url
    captcha_detect
  end

  def reload_page
    sleep 1
    @chrome.send_cmd "Page.reload", ignoreCache: false
    wait_event_fired
  end

  def execute_js(js)
      @chrome.send_cmd "Runtime.evaluate", expression: js
  end

  def wait_event_fired
      @chrome.wait_for "Page.loadEventFired"
  end

  # ページ移動
  def move_to(url)
    sleep 1
    @chrome.send_cmd "Page.navigate", url: url
    wait_event_fired
  end

  # HTMLを取得
  def get_html
    response = execute_js 'document.getElementsByTagName("html")[0].innerHTML'
    html = '<html>' + response['result']['value'] + '</html>'
  end

  def captcha_detect
    bot_detect_cnt = 0
    begin
      html = get_html
      raise CaptchaDetectedException, 'captchaが確認されました' if html.include?("captcha")
    rescue CaptchaDetectedException => e
      p e
      bot_detect_cnt += 1
      p "captcha突破試行: #{bot_detect_cnt}回目"
      doc = Nokogiri::HTML.parse(html, nil, 'UTF-8')
      return if captcha_solve(doc) == '解除成功'
      reload_page
      retry if bot_detect_cnt < 3
      p 'captcha突破エラー。Rubyを終了します'
      exit
    end
    p 'captchaはありませんでした'
  end

  def captcha_solve(doc)
    id = request_id(doc).match(/(\d.*)/)[1]
    solution = request_solution(id)
    return false unless solution
    submit_solution(solution)
    p captcha_result
  end

  def request_id(doc)
    # APIキーの読み込み
    @key = YAML.load_file("key.yaml")[:"2Capthca"]
    # data-sitekey属性の値を取得
    googlekey = doc.at_css('#recaptcha-demo')["data-sitekey"]
    method = "userrecaptcha"
    pageurl = execute_js("location.href")['result']['value']
    request_url="https://2captcha.com/in.php?key=#{@key}&method=#{method}&googlekey=#{googlekey}&pageurl=#{pageurl}"
    # captcha解除を依頼
    fetch_url(request_url)
  end

  def request_solution(id)
    action = "get"
    response_url = "https://2captcha.com/res.php?key=#{@key}&action=#{action}&id=#{id}"
    sleep 15
    retry_cnt = 0
    begin
      sleep 5
      # captcha解除コードを取得
      response_str = fetch_url(response_url)
      raise 'captcha解除前' if response_str.include?('CAPCHA_NOT_READY')
    rescue => e
      p e
      retry_cnt += 1
      p "リトライ:#{retry_cnt}回目"
      retry if retry_cnt < 10
      return false
    end
    response_str.slice(/OK\|(.*)/,1)
  end

  def submit_solution(solution)
    # 解除コードを所定のtextareaに入力
    execute_js("document.getElementById('g-recaptcha-response').innerHTML=\"#{solution}\";")
    sleep 1
    # 送信ボタンクリック
    execute_js("document.getElementById('recaptcha-demo-submit').click();")
  end

  def captcha_result
    sleep 1
    html = get_html
    doc = Nokogiri::HTML.parse(html, nil, 'UTF-8')
    doc.at_css('.recaptcha-success') ? '解除成功' : '解除失敗'
  end


  def fetch_url(url)
    sleep 1
    `curl "#{url}"`
  end

end

crawler = ChromeController.new
url = 'https://www.google.com/recaptcha/api2/demo'
crawler.open(url)

프로그램을 실행하면 reCAPTCHA 데모 페이지로 이동하여 CAPTCHA를 돌파하려고 시도합니다.
bundle exec ruby crawler.rb

마지막으로



스크래핑을 실시하는 목적이나 형태, 스크래핑으로 얻은 데이터의 취급 방법에 따라서는, 저작권법, 개인정보 보호법에 저촉해 버릴 우려가 있습니다.
여러분에게 즐거운 스크래핑 라이프가 있기를 기원합니다.

좋은 웹페이지 즐겨찾기