본문 바로가기

프로그래밍/크롤링(PYTHON)

Bot Detection / 크롤러 차단 / 크롤러 우회 #1

반응형

에이, 너가 그런거 아니지?

그냥 좋은 로직으로 크롤링만 하면 만사인줄 알았는데, 고비가 하나 더 있었다. CLI 환경에서 죽어라 크롤러를 돌리는데 자꾸 이상한 타이밍에서 Response를 못받아오거나, Connection Refuse가 발생해서 크롤러가 죽는 경우가 있었다. 내가 웹사이트 구조를 잘 이해하지 못해서 어디선가 Exception이 발생하는 건가.. 했지만, try / catch로 잡아보려고 해도 Exception은 발생하지 않았다. 

 

 

URL 문제인가?

< 의심하는거 아냐~ 그냥 실수지? >

라고 생각하면서 주소창에 여러가지 주소를 빠르게 넣어보며 웹페이지를 돌아 다니던 중, 갑자기 리다이렉션된 페이지. 정말 흠칫했는데 동시에 아차 싶었다. 지금까지 연습해온 크롤링은 정말 소규모에 불과했고, 이번에 하려는 크롤링은 꽤 많은 데이터를 긁어오기에 ( 그것도 대형 웹사이트에서 ) 이를 방지하기 위한 시스템이 존재한다는 것을 생각도 못하고 있었다.

 

디버깅의 중요성

생각해보면 정말 간단한데, 알아차리지 못했다. 자꾸 프로그램이 driver.get(URL)을 수행하는 상태에서 멈췄기 때문.. 이건 아직도 의문인데 driver.get()에 try / except를 걸어도 이상하게 exception은 발생하지 않고 프로그램이 그대로 그냥 멈춰있었다. 그래서 URL을 열고나서 Implicit Wait (WebdriverWait)을 수행, 이후에 Response를 BeautifulSoup로 파싱해서 찍어보니....

Response로 원하던 페이지가 아니라 Bot으로 탐지되어 다른 페이지가 Response로 온 것을 확인할 수 있다. 

 

그래서 우회는 어떻게?

일단 내가 아는 방법들은 이렇다.

Request의 Header에서 User-Agent 필드를 수정한다

Request의 Header에서 여러가지 필드를 임의로 작성해준다.

프록시를 사용한다.

근데, 금방 테스트 해볼 수 있는 User-Agent 방법을 써본 결과.. 소용이 없었고, 최대한 사람인 척 하는게 좋은 것 같다. 프록시의 경우 어느정도 먹히는 듯 하다가 중간에 똑같이 차단되는 모습을 보였다.

 

기록도 할 겸, User-Agent 필드를 채워서 보내는 방법을 적어보겠다.

나는 코드에서 urllib의 request를 통한 요청과 selenium의 webdriver를 통한 요청 두가지를 사용했는데, 이유는 비교적 간단하고 자바스크립트의 사용이 필요없는 부분은 빠른 urllib를 통해서 처리하기 위해서이다.

1. urllib의 User-Agent 수정

headers={

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'

}

req = urllib.request.Request(url=url, headers=headers)

 

2. Webdriver의 User-Agent 수정

firefox_profile = webdriver.FirefoxProfile()

firefox_profile.set_preference(

'general.useragent.override', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'

)

driver = webdriver.Firefox(executable_path="./geckodriver", firefox_profile=firefox_profile)

그치만 이 방법 단독으로는 소용없었다. Proxy 관련한 코드를 작성하고, 적절한 헤더 필드를 좀 더 넣어봐야겠다. 근데 결국 proxy가 답일 것 같은 것은 기분 탓인가..

 

+ 수정하는 동안 느낀 것인데.. 어쩌면 사이트에 맞춰서 천천히 크롤링하는게 더 좋을 것 같다.

반응형