selenium을 이용할 때면, webdriver로 chromedriver를 많이 사용하곤 했다. GUI가 필요없을 때에도 headless로 사용했으니 대부분이라 말할수도 있을 것 같다.
하지만 어느 순간부터 selenium을 이용하여 Google login을 자동화하는 부분을 작성하다 보면, 아래와 같은 page를 확인할 수 있다.
문제 파악
email 입력 부분을 채우고 다음 버튼을 누르게 되면, 위와 같은 브라우저 또는 앱이 안전하지 않을 수 있습니다. 라면서 더 이상의 login을 할 수 없도록 한다.
Google 입장에서는 비정상적인 login 시도 행위를 막는 것은 당연한 일이지만, 자동화가 필요한 입장에서는 여간 불편한 것은 사실이다.
조금만 더 생각해 보면 Google에서 만든 chromedriver을 가지고 비정상 행위를 한다고 했을 때, 이를 탐지하는 방법 역시 쉬울테니 언젠가는 막히리라 생각하곤 했으나 실제로 막히니 난감하기는 했다.
그렇다면 Google은 어떻게 chromedriver을 이용한 login automation을 탐지하는 것이며, undetected_chromedriver은 어떻게 이를 우회하는 것일까? 쉬운 방법으로는 firefox와 같은 다른 브라우저의 드라이버를 이용하는 것이나 궁금증을 해결하기 위하여 undetected_chromedriver에 대하여 분석해 봤다.
우회법 분석
Google이 chromedriver을 이용하는 것인지에 대하여 알 방법은 명확하지 않기에 후자인 undetected_chromedriver가 어떻게 login automation을 가능하게 해주는지에 대하여 분석해 본다.
Google APIs에서 받은 chromdriver의 cdc_adoQpoasnfa76pfcZLmcfl가 undetected_chromedriver에서 설치되는 chromedriver에서는 xyx_bakbtmdhmelauoizUBpwcp 로 바뀐 것을 확인할 수 있다.
이 부분이 무엇인지 알기 위해서는 binary의 해당 부분을 직접 확인해 보면 명확해 진다.
아래는 위의 문자열이 사용된 함수의 일부를 발췌한 것이다.
function getPageCache(opt_doc, opt_w3c) {
var doc = opt_doc || document;
var w3c = opt_w3c || false;
// |key| is a long random string, unlikely to conflict with anything else.
var key = '$cdc_adoQpoasnfa76pfcZLmcfl_';
if (w3c) {
if (!(key in doc))
doc[key] = new CacheWithUUID();
return doc[key];
} else {
if (!(key in doc))
doc[key] = new Cache();
return doc[key];
}
}
cdc_adoQpoasnfa76pfcZLmcfl는 window 객체의 여러 값을 가지고 있는 변수명들의 prefix로 사용되는데, 이 prefix는 각 build version마다 고유한 값을 가지고 있기 때문에 Google에서는 이를 이용하여 chromedriver 임을 쉽게 탐지할 수 있는 것 같다.
하지만 이러한 방식은 검색에서는 효과적일 수는 있지만, 자료의 추가/삭제에는 효율적이지 못하다.
데이터의 추가 및 삭제가 발생하면 기존 배열로부터 임시 배열을 만들어 작업을 수행하기에 최악의 경우에는 O(N)의 시간이 걸린다. 즉, 데이터의 밀고 당기는 작업이 필요하다. 추가로 배열은 동적으로 늘어나는 것이 아니라, 배열이 꽉 찼을 경우 더 큰 배열을 만들어 옮겨야 하기에 loss가 크다.
하지만 검색 차원에서는 배열의 시작 주소에 index만을 더해 data가 존재하는 곳의 주소를 바로 알 수 있기 때문에 O(1)의 시간이 걸린다.
W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'cudart64_101.dll'; dlerror: cudart64_101.dll not found
cuda가 정상적으로 설치 되었음에도 cudart64_101.dll이 없다며 에러가 발생하곤 한다.
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Wed_Oct_23_19:32:27_Pacific_Daylight_Time_2019
Cuda compilation tools, release 10.2, V10.2.89
심지어 10.2 버전의 cuda를 설치했음에도 cudart64_101.dll 즉 10.1 버전의 dll을 요구한다.
이를 위한 간단한 해결법을 기록해 놓는다.
cuda가 설치된 폴더로 들어가서, cudart64_102.dll 파일을 복사해서 cudart64_101.dll로 저장한다.
윈도우의 경우 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin 에서 확인할 수 있다.