μΉ΄ν…Œκ³ λ¦¬ 보관물: Javascript

Javascript

크둬 λ“œλΌμ΄λ²„μ™€ ν•¨κ»˜ μ…€λ ˆλŠ„μ„ μ‚¬μš©ν•  λ•Œ μ›Ή μ‚¬μ΄νŠΈμ—μ„œ 감지 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ? μ‚¬μš©ν•˜λŠ” μˆœκ°„ κ°μ§€λ©λ‹ˆλ‹€. 이둠적으둜 chromedriver와 chrome은 문자

Chromedriver둜 Selenium을 ν…ŒμŠ€νŠΈ ν•œ κ²°κ³Ό μžλ™ν™”κ°€ μ „ν˜€ 없어도 일뢀 νŽ˜μ΄μ§€μ—μ„œ Selenium을 μ‚¬μš©ν•˜κ³  μžˆμŒμ„ 감지 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. Seleniumκ³Ό Xephyr을 톡해 크둬을 μ‚¬μš©ν•˜μ—¬ μˆ˜λ™μœΌλ‘œ νƒμƒ‰ν•˜λŠ” κ²½μš°μ—λ„ μ˜μ‹¬μŠ€λŸ¬μš΄ ν™œλ™μ΄ κ°μ§€λ˜μ—ˆλ‹€λŠ” νŽ˜μ΄μ§€κ°€ μ’…μ’… λ‚˜νƒ€λ‚©λ‹ˆλ‹€. μ‚¬μš©μž μ—μ΄μ „νŠΈμ™€ λΈŒλΌμš°μ € 지문을 ν™•μΈν–ˆμœΌλ©° λͺ¨λ‘ 일반 크둬 λΈŒλΌμš°μ €μ™€ λ™μΌν•©λ‹ˆλ‹€.

정상적인 크둬 으둜이 μ‚¬μ΄νŠΈλ₯Ό νƒμƒ‰ν•˜λ©΄ λͺ¨λ“  것이 잘 μž‘λ™ν•˜μ§€λ§Œ Selenium을 μ‚¬μš©ν•˜λŠ” μˆœκ°„ κ°μ§€λ©λ‹ˆλ‹€.

이둠적으둜 chromedriver와 chrome은 문자 κ·ΈλŒ€λ‘œ λͺ¨λ“  μ›Ή μ„œλ²„μ™€ λ™μΌν•˜κ²Œ λ³΄μ΄μ§€λ§Œ μ–΄λ–»κ²Œ λ“  감지 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μ›ν•˜λ©΄ λ‹€μŒμ„ μ‹œλ„ν•˜μ‹­μ‹œμ˜€.

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=1, size=(1600, 902))
display.start()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--disable-extensions')
chrome_options.add_argument('--profile-directory=Default')
chrome_options.add_argument("--incognito")
chrome_options.add_argument("--disable-plugins-discovery");
chrome_options.add_argument("--start-maximized")
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.delete_all_cookies()
driver.set_window_size(800,800)
driver.set_window_position(0,0)
print 'arguments done'
driver.get('http://stubhub.com')

stubhubλ₯Ό νƒμƒ‰ν•˜λ©΄ ν•˜λ‚˜ λ˜λŠ” 두 개의 μš”μ²­ λ‚΄μ—μ„œ λ¦¬λ””λ ‰μ…˜λ˜κ³  β€˜μ°¨λ‹¨β€™λ©λ‹ˆλ‹€. λ‚˜λŠ” 이것을 μ‘°μ‚¬ν•˜κ³  있으며 μ‚¬μš©μžκ°€ μ…€λ ˆλŠ„μ„ μ‚¬μš©ν•˜κ³  μžˆμŒμ„ μ–΄λ–»κ²Œ μ•Œ 수 μžˆλŠ”μ§€ μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€.

그듀은 κ·Έκ±Έ μ–΄λ–»κ²Œ ν–‡μ–΄?

μ—…λ°μ΄νŠΈ νŽΈμ§‘ :

Firefox에 Selenium IDE ν”ŒλŸ¬κ·ΈμΈμ„ μ„€μΉ˜ν–ˆμœΌλ©° μΆ”κ°€ ν”ŒλŸ¬κ·ΈμΈλ§ŒμœΌλ‘œ 일반 firefox λΈŒλΌμš°μ €μ—μ„œ stubhub.com에 갈 λ•Œ κΈˆμ§€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

νŽΈμ§‘ν•˜λ‹€:

Fiddlerλ₯Ό μ‚¬μš©ν•˜μ—¬μ£Όκ³ λ°›λŠ” HTTP μš”μ²­μ„ λ³Ό λ•Œ β€˜κ°€μ§œ λΈŒλΌμš°μ €β€™μš”μ²­μ΄ 응닡 헀더에 β€˜λ…Έ μΊμ‹œ μ—†μŒβ€™μ„ κ°€μ§€κ³  μžˆμŒμ„ μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

νŽΈμ§‘ν•˜λ‹€:

Javascript의 Selenium Webdriver νŽ˜μ΄μ§€μ— μžˆλ‹€λŠ” 것을 κ°μ§€ν•˜λŠ” 방법 이 μžˆμŠ΅λ‹ˆκΉŒ? μ›Ή λ“œλΌμ΄λ²„λ₯Ό μ‚¬μš©ν•  λ•Œ 감지 ν•  μˆ˜μžˆλŠ” 방법이 μ—†μ–΄μ•Όν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜μ΄ μ¦κ±°λŠ” κ·Έλ ‡μ§€ μ•Šλ‹€λŠ” 것을 μ•”μ‹œν•©λ‹ˆλ‹€.

νŽΈμ§‘ν•˜λ‹€:

이 μ‚¬μ΄νŠΈλŠ” μ„œλ²„μ— 지문을 μ—…λ‘œλ“œν•˜μ§€λ§Œ 크둬을 μ‚¬μš©ν•  λ•Œ μ…€λ ˆλŠ„μ˜ 지문이 μ§€λ¬Έκ³Ό λ™μΌν•˜λ‹€λŠ” 것을 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.

νŽΈμ§‘ν•˜λ‹€:

이것은 μ„œλ²„λ‘œ λ³΄λ‚΄λŠ” μ§€λ¬Έ νŽ˜μ΄λ‘œλ“œ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

{"appName":"Netscape","platform":"Linuxx86_64","cookies":1,"syslang":"en-US","userlang":"en-US","cpu":"","productSub":"20030107","setTimeout":1,"setInterval":1,"plugins":{"0":"ChromePDFViewer","1":"ShockwaveFlash","2":"WidevineContentDecryptionModule","3":"NativeClient","4":"ChromePDFViewer"},"mimeTypes":{"0":"application/pdf","1":"ShockwaveFlashapplication/x-shockwave-flash","2":"FutureSplashPlayerapplication/futuresplash","3":"WidevineContentDecryptionModuleapplication/x-ppapi-widevine-cdm","4":"NativeClientExecutableapplication/x-nacl","5":"PortableNativeClientExecutableapplication/x-pnacl","6":"PortableDocumentFormatapplication/x-google-chrome-pdf"},"screen":{"width":1600,"height":900,"colorDepth":24},"fonts":{"0":"monospace","1":"DejaVuSerif","2":"Georgia","3":"DejaVuSans","4":"TrebuchetMS","5":"Verdana","6":"AndaleMono","7":"DejaVuSansMono","8":"LiberationMono","9":"NimbusMonoL","10":"CourierNew","11":"Courier"}}

μ…€λ ˆλŠ„κ³Ό ν¬λ‘¬μ—μ„œ 동일

νŽΈμ§‘ν•˜λ‹€:

VPN은 일회용으둜 μž‘λ™ν•˜μ§€λ§Œ 첫 νŽ˜μ΄μ§€λ₯Όλ‘œλ“œ ν•œ 후에 κ°μ§€λ©λ‹ˆλ‹€. λΆ„λͺ…νžˆ μ…€λ ˆλŠ„μ„ κ°μ§€ν•˜κΈ° μœ„ν•΄ 일뢀 μžλ°” μŠ€ν¬λ¦½νŠΈκ°€ μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€.



λ‹΅λ³€

Mac μ‚¬μš©μžμ˜ 경우

cdc_Vim λ˜λŠ” Perl을 μ‚¬μš©ν•˜μ—¬ λ³€μˆ˜ λ°”κΎΈκΈ°

당신은 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€ vim, λ˜λŠ” @Vic Seedoubleyew이 Erti – 크리슀 Eelmaa @에 μ˜ν•΄μ΄ μ§ˆλ¬Έμ— λŒ€ν•΄ μ§€μ λŒ€λ‘œ perl의 ꡐ체 cdc_에 λ³€μˆ˜ chromedriver( Erti – 크리슀 Eelmaa 더 κ·Έ λ³€μˆ˜μ— λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ @에 μ˜ν•΄ μ°Έμ‘° κ²Œμ‹œλ¬Όμ„ ). μ‚¬μš© vimλ˜λŠ” perlμ†ŒμŠ€ μ½”λ“œλ₯Ό 컴파일 λ˜λŠ” ν—₯슀 νŽΈμ§‘κΈ°λ₯Ό μ‚¬μš© ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 원본 chromedriver을 νŽΈμ§‘ν•˜κΈ° 전에 사본을 λ§Œλ“€μ–΄ λ‘μ‹­μ‹œμ˜€. λ˜ν•œ μ•„λž˜ 방법을 ν…ŒμŠ€νŠΈν–ˆμŠ΅λ‹ˆλ‹€ chromedriver version 2.41.578706.


Vim μ‚¬μš©

vim /path/to/chromedriver

μœ„μ˜ 쀄을 μ‹€ν–‰ν•˜λ©΄ μ•„λ§ˆλ„ λ§Žμ€ νš‘μ„€μˆ˜μ„€μ„ 보게 될 κ²ƒμž…λ‹ˆλ‹€. λ‹€μŒμ„ μˆ˜ν–‰ν•˜μ‹­μ‹œμ˜€.

  1. cdc_을 μž…λ ₯ν•˜κ³ μ„ /cdc_눌러 κ²€μƒ‰ν•˜μ‹­μ‹œμ˜€ return.
  2. λ₯Ό 눌러 νŽΈμ§‘μ„ ν™œμ„±ν™”ν•˜μ‹­μ‹œμ˜€ a.
  3. κΈˆμ•‘μ„ $cdc_lasutopfhvcZLmcflμ‚­μ œν•˜κ³  μ‚­μ œ 된 λ‚΄μš©μ„ 같은 μ–‘μ˜ 문자둜 λ°”κΏ‰λ‹ˆλ‹€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ chromedriverμ‹€νŒ¨ν•©λ‹ˆλ‹€.
  4. νŽΈμ§‘μ΄ λλ‚˜λ©΄λ₯Ό λˆ„λ¦…λ‹ˆλ‹€ esc.
  5. λ³€κ²½ 사항을 μ €μž₯ν•˜κ³  μ’…λ£Œν•˜λ €λ©΄μ„ μž…λ ₯ν•˜κ³ μ„ :wq!λˆ„λ₯΄μ‹­μ‹œμ˜€ return.
  6. λ³€κ²½ 사항을 μ €μž₯ν•˜μ§€ μ•Šκ³  μ’…λ£Œν•˜λ €λ©΄μ„ μž…λ ₯ν•˜κ³ μ„ :q!λˆ„λ¦…λ‹ˆλ‹€ return.
  7. λλ‚¬μŠ΅λ‹ˆλ‹€.

λ³€κ²½λœ κ²ƒμœΌλ‘œ μ΄λ™ν•˜μ—¬ chromedriver두 번 ν΄λ¦­ν•˜μ‹­μ‹œμ˜€. terminal창이 μ—΄λ¦½λ‹ˆλ‹€. killed좜λ ₯에 ν‘œμ‹œλ˜μ§€ μ•ŠμœΌλ©΄ λ“œλΌμ΄λ²„λ₯Ό μ„±κ³΅μ μœΌλ‘œ λ³€κ²½ ν•œ κ²ƒμž…λ‹ˆλ‹€.


νŽ„ μ‚¬μš©ν•˜κΈ°

을 λŒ€μ²΄ μ•„λž˜μ˜ 라인 cdc_을 κ°€μ§„ dog_:

perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver

λŒ€μ²΄ λ¬Έμžμ—΄μ΄ 검색 λ¬Έμžμ—΄κ³Ό λ™μΌν•œ 수의 문자λ₯Ό κ°–λŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€ chromedriver. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

νŽ„ μ„€λͺ…

s///g 은 λ¬Έμžμ—΄μ„ κ²€μƒ‰ν•˜μ—¬ μ „μ²΄μ μœΌλ‘œ λ‹€λ₯Έ λ¬Έμžμ—΄λ‘œ ꡐ체 함을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€ (λͺ¨λ“  ν•­λͺ©μ„ λŒ€μ²΄ 함).

예λ₯Ό λ“€μ–΄ s/string/replacment/g

κ·Έλž˜μ„œ,

s/// λ¬Έμžμ—΄ 검색 및 ꡐ체λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

cdc_ 검색 λ¬Έμžμ—΄μž…λ‹ˆλ‹€.

dog_ ꡐ체 λ¬Έμžμ—΄μž…λ‹ˆλ‹€.

g λ¬Έμžμ—΄μ˜ λͺ¨λ“  λ°œμƒμ„ λŒ€μ²΄ν•˜λŠ” μ „μ—­ ν‚€μž…λ‹ˆλ‹€.

Perl ꡐ체가 μž‘λ™ν–ˆλŠ”μ§€ ν™•μΈν•˜λŠ” 방법

λ‹€μŒ 쀄은 λͺ¨λ“  검색 λ¬Έμžμ—΄μ„ μΈμ‡„ν•©λ‹ˆλ‹€ cdc_.

perl -ne 'while(/cdc_/g){print "$&\n";}' /path/to/chromedriver

이것이 아무것도 λ°˜ν™˜λ˜μ§€ μ•ŠμœΌλ©΄ cdc_ꡐ체 된 κ²ƒμž…λ‹ˆλ‹€.

λ°˜λŒ€λ‘œ λ‹€μŒμ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

perl -ne 'while(/dog_/g){print "$&\n";}' /path/to/chromedriver

λŒ€μ²΄ λ¬Έμžμ—΄ dog_이 이제 chromedriverλ°”μ΄λ„ˆλ¦¬ 에 μžˆλŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€ . 이 경우 ꡐ체 λ¬Έμžμ—΄μ΄ μ½˜μ†”μ— μΈμ‡„λ©λ‹ˆλ‹€.

λ³€κ²½λœ κ²ƒμœΌλ‘œ μ΄λ™ν•˜μ—¬ chromedriver두 번 ν΄λ¦­ν•˜μ‹­μ‹œμ˜€. terminal창이 μ—΄λ¦½λ‹ˆλ‹€. killed좜λ ₯에 ν‘œμ‹œλ˜μ§€ μ•ŠμœΌλ©΄ λ“œλΌμ΄λ²„λ₯Ό μ„±κ³΅μ μœΌλ‘œ λ³€κ²½ ν•œ κ²ƒμž…λ‹ˆλ‹€.


마무리

chromedriver이진을 λ³€κ²½ ν•œ ν›„ λ³€κ²½λœ chromedriver이진 의 이름 이 chromedriver이고 원본 이진이 μ›λž˜ μœ„μΉ˜μ—μ„œ μ΄λ™ν•˜κ±°λ‚˜ 이름이 λ°”λ€Œ μ—ˆλŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€.


이 방법에 λŒ€ν•œ λ‚˜μ˜ κ²½ν—˜

이전에 μ›Ή μ‚¬μ΄νŠΈμ—μ„œ λ‘œκ·ΈμΈμ„ μ‹œλ„ν•˜λŠ” λ™μ•ˆ κ°μ§€λ˜μ—ˆμ§€λ§Œ cdc_λ™μΌν•œ 크기의 λ¬Έμžμ—΄λ‘œ ꡐ체 ν•œ ν›„ 둜그인 ν•  μˆ˜μžˆμ—ˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ λ§ν–ˆλ“―μ΄ 이미 감지 된 경우 이 방법을 μ‚¬μš©ν•œ 후에도 λ‹€λ₯Έ λ§Žμ€ μ΄μœ κ°€ μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ VPN, λ‹€λ₯Έ λ„€νŠΈμ›Œν¬ λ˜λŠ” μžμ‹ μ΄μžˆλŠ” 것을 μ‚¬μš©ν•˜μ—¬ 탐지 ν•œ μ‚¬μ΄νŠΈμ— μ•‘μ„ΈμŠ€ν•΄μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.


λ‹΅λ³€

기본적으둜 μ…€λ ˆλŠ„ 감지 κΈ°λŠ₯은 μ…€λ ˆλŠ„μœΌλ‘œ 싀행될 λ•Œ λ‚˜νƒ€λ‚˜λŠ” 미리 μ •μ˜ 된 μžλ°” 슀크립트 λ³€μˆ˜λ₯Ό ν…ŒμŠ€νŠΈν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 봇 검색 μŠ€ν¬λ¦½νŠΈλŠ” 일반적으둜 μ–΄λ–€ 단어λ₯Ό ν¬ν•¨ν•˜λŠ” (μ°½ 개체)에 λ³€μˆ˜μ˜μ—μ„œ β€œμ…€λ ˆλŠ„β€/ β€œwebdriver”, λ˜ν•œλΌλŠ” λ¬Έμ„œ λ³€μˆ˜ λͺ¨μ–‘ $cdc_κ³Ό $wdc_. λ¬Όλ‘ ,이 λͺ¨λ“  것은 μ‚¬μš©μ€‘μΈ λΈŒλΌμš°μ €μ— 따라 λ‹€λ¦…λ‹ˆλ‹€. λͺ¨λ“  λ‹€λ₯Έ λΈŒλΌμš°μ €λŠ” λ‹€λ₯Έ 것을 λ…ΈμΆœμ‹œν‚΅λ‹ˆλ‹€.

λ‚˜λ₯Ό μœ„ν•΄, λ‚˜λŠ”, κ·Έλž˜μ„œ 크둬을 μ‚¬μš© λ‚˜λŠ”ν–ˆλ‹€λŠ” 것을 λͺ¨λ‘ ν•  κ·Έ 보μž₯ν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€ $cdc_λ¬Έμ„œ λ³€μˆ˜λ‘œ 더 이상 μ‘΄μž¬ν•˜μ§€ μ•Šκ³  μ§œμž” (λ‹€μš΄λ‘œλ“œ chromedriver μ†ŒμŠ€ μ½”λ“œ μˆ˜μ • chromedriver 재 컴파일 $cdc_λ‹€λ₯Έ 이름.)

이것은 chromedriverμ—μ„œ μˆ˜μ • ν•œ κΈ°λŠ₯μž…λ‹ˆλ‹€.

call_function.js :

function getPageCache(opt_doc) {
  var doc = opt_doc || document;
  //var key = '$cdc_asdjflasutopfhvcZLmcfl_';
  var key = 'randomblabla_';
  if (!(key in doc))
    doc[key] = new Cache();
  return doc[key];
}

(λͺ¨λ“  λ‚΄κ°€ μ„€μ • ν•œ 주석을 μ°Έκ³  $cdc_에 randomblabla_.

λ‹€μŒμ€ 봇 λ„€νŠΈμ›Œν¬κ°€ μ‚¬μš©ν•  μˆ˜μžˆλŠ” 기술 쀑 일뢀λ₯Ό λ³΄μ—¬μ£ΌλŠ” μ˜μ‚¬ μ½”λ“œμž…λ‹ˆλ‹€.

runBotDetection = function () {
    var documentDetectionKeys = [
        "__webdriver_evaluate",
        "__selenium_evaluate",
        "__webdriver_script_function",
        "__webdriver_script_func",
        "__webdriver_script_fn",
        "__fxdriver_evaluate",
        "__driver_unwrapped",
        "__webdriver_unwrapped",
        "__driver_evaluate",
        "__selenium_unwrapped",
        "__fxdriver_unwrapped",
    ];

    var windowDetectionKeys = [
        "_phantom",
        "__nightmare",
        "_selenium",
        "callPhantom",
        "callSelenium",
        "_Selenium_IDE_Recorder",
    ];

    for (const windowDetectionKey in windowDetectionKeys) {
        const windowDetectionKeyValue = windowDetectionKeys[windowDetectionKey];
        if (window[windowDetectionKeyValue]) {
            return true;
        }
    };
    for (const documentDetectionKey in documentDetectionKeys) {
        const documentDetectionKeyValue = documentDetectionKeys[documentDetectionKey];
        if (window['document'][documentDetectionKeyValue]) {
            return true;
        }
    };

    for (const documentKey in window['document']) {
        if (documentKey.match(/\$[a-z]dc_/) && window['document'][documentKey]['cache_']) {
            return true;
        }
    }

    if (window['external'] && window['external'].toString() && (window['external'].toString()['indexOf']('Sequentum') != -1)) return true;

    if (window['document']['documentElement']['getAttribute']('selenium')) return true;
    if (window['document']['documentElement']['getAttribute']('webdriver')) return true;
    if (window['document']['documentElement']['getAttribute']('driver')) return true;

    return false;
};

μ‚¬μš©μž @szx에 λ”°λ₯΄λ©΄ 16 μ§„ νŽΈμ§‘κΈ°μ—μ„œ chromedriver.exeλ₯Ό μ—΄κ³  μ‹€μ œλ‘œ μ»΄νŒŒμΌν•˜μ§€ μ•Šκ³  μˆ˜λ™μœΌλ‘œ ꡐ체λ₯Ό μˆ˜ν–‰ ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.


λ‹΅λ³€

μš°λ¦¬κ°€ 이미 질문과 κ²Œμ‹œ 된 λ‹΅λ³€μ—μ„œ μ•Œμ•„ λ‚Έ κ²ƒμ²˜λŸΌ, μ›Ή μŠ€ν¬λž˜ν•‘ λ°©μ§€ 및 β€œDistil Networks” λΌλŠ” 봇 탐지 μ„œλΉ„μŠ€κ°€ 여기에 μžˆμŠ΅λ‹ˆλ‹€. 그리고 νšŒμ‚¬ CEO의 인터뷰 에 λ”°λ₯΄λ©΄ :

μƒˆλ‘œμš΄ 봇을 λ§Œλ“€ μˆ˜λŠ” μžˆμ§€λ§Œ Selenium을 μ‚¬μš©μ€‘μΈ λ„κ΅¬λ‘œ 식별 ν•  μˆ˜μžˆλŠ” 방법을 μ°Ύμ•„μ„œ ν•΄λ‹Ή λ΄‡μ—μ„œ λ°˜λ³΅λ˜λŠ” νšŸμˆ˜μ— 관계없이 Selenium을 μ°¨λ‹¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ . μš°λ¦¬λŠ” μ§€κΈˆ 파이썬과 λ§Žμ€ λ‹€λ₯Έ 기술둜 κ·Έλ ‡κ²Œν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•œ μœ ν˜•μ˜ λ΄‡μ—μ„œ νŒ¨ν„΄μ΄ λ“±μž₯ν•˜λ©΄ μ‚¬μš©ν•˜λŠ” κΈ°μˆ μ„ λ¦¬λ²„μŠ€ μ—”μ§€λ‹ˆμ–΄λ§ν•˜μ—¬ μ•…μ˜μ  인 κ²ƒμœΌλ‘œ μ‹λ³„ν•©λ‹ˆλ‹€.

그듀이 μ–΄λ–»κ²Œ Selenium을 μ •ν™•ν•˜κ²Œ κ°μ§€ν•˜λŠ”μ§€ μ΄ν•΄ν•˜λ €λ©΄ μ‹œκ°„κ³Ό μΆ”κ°€ κ³Όμ œκ°€ ν•„μš”ν•˜μ§€λ§Œ, μ§€κΈˆ μš°λ¦¬κ°€ 말할 μˆ˜μžˆλŠ” 것은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

  • 그것은 μ…€λ ˆλŠ„μœΌλ‘œ μ·¨ν•œ 행동과 관련이 μ—†μŠ΅λ‹ˆλ‹€. 일단 μ‚¬μ΄νŠΈλ₯Ό νƒμƒ‰ν•˜λ©΄ μ¦‰μ‹œ κ°μ§€λ˜μ–΄ κΈˆμ§€λ©λ‹ˆλ‹€. μ•‘μ…˜ 사이에 μΈμœ„μ μΈ λ¬΄μž‘μœ„ 지연을 μΆ”κ°€ν•˜λ €κ³ ν–ˆμŠ΅λ‹ˆλ‹€. νŽ˜μ΄μ§€κ°€λ‘œλ“œ 된 ν›„ μΌμ‹œ μ€‘μ§€ν•˜μ‹­μ‹œμ˜€.
  • λΈŒλΌμš°μ € 지문에 κ΄€ν•œ 것이 μ•„λ‹™λ‹ˆλ‹€. μ‹œν¬λ¦Ώ λͺ¨λ“œκ°€ μ•„λ‹Œ κΉ”λ”ν•œ ν”„λ‘œνŒŒμΌλ‘œ μ—¬λŸ¬ λΈŒλΌμš°μ €μ—μ„œ μ‹œλ„ν•΄λ³΄μ‹­μ‹œμ˜€. λ„μ›€μ΄λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.
  • μΈν„°λ·°μ˜ νžŒνŠΈμ— λ”°λ₯΄λ©΄, 이것은 β€œμ—­ μ—”μ§€λ‹ˆμ–΄λ§β€μ΄μ—ˆκΈ° λ•Œλ¬Έμ— λΈŒλΌμš°μ €μ—μ„œ 일뢀 JS μ½”λ“œκ°€ μ‹€ν–‰λ˜μ–΄ μ…€λ ˆλŠ„ μ›Ή λ“œλΌμ΄λ²„λ₯Ό 톡해 μžλ™ν™” 된 λΈŒλΌμš°μ €μž„μ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

λͺ…ν™•ν•˜κ²Œ λ‹΅λ³€μœΌλ‘œ κ²Œμ‹œν•˜κΈ°λ‘œ κ²°μ •ν–ˆμŠ΅λ‹ˆλ‹€.

크둬 λ“œλΌμ΄λ²„μ™€ ν•¨κ»˜ μ…€λ ˆλŠ„μ„ μ‚¬μš©ν•  λ•Œ μ›Ή μ‚¬μ΄νŠΈμ—μ„œ 감지 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

예.


λ˜ν•œ μ‹€ν—˜ν•˜μ§€ μ•Šμ€ 것은 이전 μ…€λ ˆλŠ„ 및 이전 λΈŒλΌμš°μ € λ²„μ „μž…λ‹ˆλ‹€. 이둠적으둜 Distil Networks 봇 감지기가 ν˜„μž¬ μ˜μ‘΄ν•˜κ³ μžˆλŠ” νŠΉμ • μ‹œμ μ—μ„œ μ…€λ ˆλŠ„μ— κ΅¬ν˜„ / μΆ”κ°€ 된 κ²ƒμ΄μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 그렇닀면이 경우 κ΄€λ ¨ 변경이 λ°œμƒν•œ 지점 / 버전을 κ°μ§€ν•˜κ³  (κ²€μΆœκΈ°λ₯Ό κ°μ§€ν•˜μž) λ³€κ²½ 둜그 및 λ³€κ²½ μ„ΈνŠΈλ₯Ό μ‚΄νŽ΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μ›Ή λ“œλΌμ΄λ²„ 기반 λΈŒλΌμš°μ €λ₯Ό νƒμ§€ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” κΈ°λŠ₯은 λ¬΄μ—‡μž…λ‹ˆκΉŒ? ν…ŒμŠ€νŠΈν•΄μ•Ό ν•  이둠 μΌλΏμž…λ‹ˆλ‹€.


λ‹΅λ³€

wellsfargo.comμ—μ„œ κ΅¬ν˜„λ˜λŠ” 예 :

try {
 if (window.document.documentElement.getAttribute("webdriver")) return !+[]
} catch (IDLMrxxel) {}
try {
 if ("_Selenium_IDE_Recorder" in window) return !+""
} catch (KknKsUayS) {}
try {
 if ("__webdriver_script_fn" in document) return !+""

λ‹΅λ³€

λ‚œλ… ν™” 된 JavaScript κ²°κ³Ό

크둬 λ“œλΌμ΄λ²„ μ†ŒμŠ€ μ½”λ“œλ₯Ό ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€. λΈŒλΌμš°μ €μ— 일뢀 μžλ°” 슀크립트 파일이 μ‚½μž…λ©λ‹ˆλ‹€.
이 링크의 λͺ¨λ“  μžλ°” 슀크립트 νŒŒμΌμ€
https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/ μ›Ή νŽ˜μ΄μ§€μ— μ‚½μž…λ©λ‹ˆλ‹€.

κ·Έλž˜μ„œ λ¦¬λ²„μŠ€ μ—”μ§€λ‹ˆμ–΄λ§μ„ μ‚¬μš© ν•˜κ³  16 μ§„μˆ˜ νŽΈμ§‘μœΌλ‘œ js νŒŒμΌμ„ λ‚œλ… ν™” ν–ˆμŠ΅λ‹ˆλ‹€. μ΄μ œλŠ” 더 이상 μžλ°” 슀크립트 λ³€μˆ˜, ν•¨μˆ˜ 이름 및 κ³ μ • λ¬Έμžμ—΄μ΄ μ…€λ ˆλŠ„ ν™œλ™μ„ λ°œκ²¬ν•˜λŠ” 데 μ‚¬μš©λ˜μ§€ μ•Šμ•˜λ‹€κ³  ν™•μ‹ ν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ—¬μ „νžˆ 일뢀 μ‚¬μ΄νŠΈμ™€ reCaptchaλŠ” μ…€λ ˆλŠ„μ„ κ°μ§€ν•©λ‹ˆλ‹€!
μ–΄μ©Œλ©΄ 그듀은 chromedriver js μ‹€ν–‰μœΌλ‘œ μΈν•œ μˆ˜μ • 사항을 ν™•μΈν•©λ‹ˆλ‹€ πŸ™‚

νŽΈμ§‘ 1 :

Chrome β€˜λ„€λΉ„κ²Œμ΄ν„°β€™λ§€κ°œ λ³€μˆ˜ μˆ˜μ •

β€˜λ„€λΉ„κ²Œμ΄ν„°β€™μ— chromedriverλ₯Ό μ‚¬μš©ν•˜μ—¬ κ°„λ‹¨νžˆ μ•Œμ•„λ‚΄λŠ” λͺ‡ κ°€μ§€ 맀개 λ³€μˆ˜κ°€ μžˆμŒμ„ λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. 맀개 λ³€μˆ˜λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • β€œnavigator.webdriver” μžλ™ν™”λ˜μ§€ μ•Šμ€ λͺ¨λ“œμ—μ„œλŠ” β€˜μ •μ˜λ˜μ§€ μ•ŠμŒβ€™μž…λ‹ˆλ‹€. μžλ™ λͺ¨λ“œμ—μ„œλŠ” β€˜trueβ€™μž…λ‹ˆλ‹€.
  • β€œnavigator.plugins” ν—€λ“œλ¦¬μŠ€ 크둬의 κΈΈμ΄λŠ” 0μž…λ‹ˆλ‹€. ν”ŒλŸ¬κ·ΈμΈ 길이 확인 ν”„λ‘œμ„ΈμŠ€λ₯Ό 속이기 μœ„ν•΄ κ°€μ§œ μš”μ†Œλ₯Ό μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
  • ” navigator.languages” λŠ” κΈ°λ³Έ 크둬 κ°’ β€˜[ β€œen-US”, β€œen”, β€œes”]β€™λ‘œ μ„€μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ λ‚΄κ°€ ν•„μš”ν•œ 것은 μ›Ή νŽ˜μ΄μ§€μ—μ„œ μžλ°” 슀크립트λ₯Ό μ‹€ν–‰ν•˜λŠ” 크둬 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄μ—ˆμŠ΅λ‹ˆλ‹€. 기사에 제곡된 js μ½”λ“œ 둜 ν™•μž₯ 을 λ§Œλ“€κ³  λ‹€λ₯Έ 기사 λ₯Ό μ‚¬μš© ν•˜μ—¬ μ••μΆ• ν™•μž₯자λ₯Ό λ‚΄ ν”„λ‘œμ νŠΈμ— μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€. 값을 μ„±κ³΅μ μœΌλ‘œ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ—¬μ „νžˆ 아무것도 λ°”λ€Œμ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€!

λ‚˜λŠ” 이와 같은 λ‹€λ₯Έ λ³€μˆ˜λ₯Ό μ°Ύμ§€ λͺ»ν–ˆμ§€λ§Œ 그것이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ˜λ―Έν•˜μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. μ—¬μ „νžˆ reCaptchaλŠ” Chromedriverλ₯Ό κ°μ§€ν•˜λ―€λ‘œ 더 λ§Žμ€ λ³€μˆ˜λ₯Ό λ³€κ²½ν•΄μ•Όν•©λ‹ˆλ‹€. λ‹€μŒ λ‹¨κ³„λŠ” λ‚΄κ°€ μ›ν•˜λŠ”ν•˜μ§€ μ•ŠλŠ” 것이 κ²€μΆœκΈ° μ„œλΉ„μŠ€μ˜ λ¦¬λ²„μŠ€ μ—”μ§€λ‹ˆμ–΄λ§ν•΄μ•Όν•œλ‹€.

이제이 μžλ™ν™” ν”„λ‘œμ„ΈμŠ€μ— 더 λ§Žμ€ μ‹œκ°„μ„ λ³΄λ‚΄κ±°λ‚˜ λ‹€λ₯Έ 방법을 μ°Ύμ•„ λ³Ό κ°€μΉ˜κ°€ μ—†μŠ΅λ‹ˆλ‹€!


λ‹΅λ³€

크둬의 νŠΉμ • μ‚¬μš©μž ν”„λ‘œν•„κ³Ό ν•¨κ»˜ μ…€λ ˆλŠ„μ„ μ‚¬μš©ν•˜μ‹­μ‹œμ˜€. 그러면 νŠΉμ • μ‚¬μš©μžλ‘œ μ‚¬μš©ν•˜κ³  μ›ν•˜λŠ” 것을 μ •μ˜ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κ²Œν•˜λ©΄ β€˜μ‹€μ œβ€™μ‚¬μš©μžλ‘œ μ‹€ν–‰λ˜λ©° 일뢀 ν”„λ‘œμ„ΈμŠ€ νƒμƒ‰κΈ°μ—μ„œ 크둬 ν”„λ‘œμ„ΈμŠ€λ₯Όλ³΄κ³  νƒœκ·Έμ™€μ˜ 차이점을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

username = os.getenv("USERNAME")
userProfile = "C:\\Users\\" + username + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default"
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir={}".format(userProfile))
# add here any tag you want.
options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors", "safebrowsing-disable-download-protection", "safebrowsing-disable-auto-update", "disable-client-side-phishing-detection"])
chromedriver = "C:\Python27\chromedriver\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
browser = webdriver.Chrome(executable_path=chromedriver, chrome_options=options)

크둬 νƒœκ·Έ λͺ©λ‘μ€ μ—¬κΈ°


λ‹΅λ³€

partial interface Navigator {
readonly attribute boolean webdriver;
};

Navigator μΈν„°νŽ˜μ΄μŠ€μ˜ webdriver IDL 속성은 webdriver-active ν”Œλž˜κ·Έμ˜ 값을 λ¦¬ν„΄ν•΄μ•Όν•©λ‹ˆλ‹€. 초기 값은 falseμž…λ‹ˆλ‹€.

이 속성을 톡해 μ›Ή μ‚¬μ΄νŠΈλŠ” WebDriverκ°€ μ‚¬μš©μž μ—μ΄μ „νŠΈλ₯Ό μ œμ–΄ν•˜κ³  μžˆμŒμ„ ν™•μΈν•˜κ³  μ„œλΉ„μŠ€ κ±°λΆ€ 곡격을 μ™„ν™”ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2017 W3C Editor의 WebDriver μ΄ˆμ•ˆ μ—μ„œ 직접 κ°€μ Έμ˜¨ 것 μž…λ‹ˆλ‹€. 이것은 μ΅œμ†Œν•œ μ…€λ ˆλŠ„ λ“œλΌμ΄λ²„μ˜ ν–₯ν›„ 반볡이 μ˜€μš©μ„ λ°©μ§€ν•˜κΈ° μœ„ν•΄ 식별 될 수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. ꢁ극적으둜 μ†ŒμŠ€ μ½”λ“œκ°€ μ—†μœΌλ©΄ 크둬 λ“œλΌμ΄λ²„λ₯Ό μ •ν™•ν•˜κ²Œ 감지 ν•  μˆ˜μ—†λŠ” 원인을 νŒŒμ•…ν•˜κΈ°κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€.