웹 크롤링 중 일어날 수 있는 오류들 정리
0. 당연히 가장 많이 발생하는 오류는 기본적인 문법을 틀려서일 것이다. 기초가 부족한 상황이라면 웹 크롤링의 개괄적인 내용을 먼저 이해하고 프로그래밍을 시작하는게 결과적으로 시간을 줄이는 길이다. 인터넷의 크롤링 관련 포스팅 중 가장 양질의 포스팅을 공유한다. 실제 코드를 예시로 들어 초보자도 이해하기 쉽게 차근차근 설명되어있다.
https://book.coalastudy.com/data-crawling/
1. 정적크롤링을 위한 Requests 라이브러리에서 발생할 수 있는 오류
import requests url = 'https://youngseokim.tistory.com' html = requests.get(url) soup = BeautifulSoup(html.text, 'html.parser')
만일 위와같은 코드 이후 soup.findAll이든, soup.find을 하든 이상하게 원하는대로 요소가 잘 찾아지지 않는다면, 애초에 원하는 웹주소의 내용을 받아오는 request.get 부분에서 문제가 생겼을 수 있다. soup를 print해보고 대강 읽어보면 내가 원하는 페이지가 제대로 받아와졌는지 아닌지 확인할 수 있을 것이다.
대부분은 User-Agent를 설정함으로써 해결할 수 있다. 위의 코드는 아래와같이 수정되어야한다.
import requests url = 'https://youngseokim.tistory.com' headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.39.132 Safari/53.36'} html = requests.get(url, headers = headers) soup = BeautifulSoup(html.text, 'html.parser')
주의할 점은 'User-Agent': 뒤의 문구는 개인의 User-Agent 를 확인해야한다는 점이다. 확인하는 법은 아래 포스팅을 참고하자.
https://backkom-blog.tistory.com/entry/Chrome크롬-웹-브라우저-User-Agent-확인하기
2. 동적 크롤링을 위한 Selenium 라이브러리에서 발생할 수 있는 오류
from selenium import webdriver driver = webdriver.Chrome('/Users/Desktop/project/chromedriver') url = 'https://youngseokim.tistory.com' driver.get(url) driver.find_element_by_xpath('/html/body/div[12]/div[2]/div/h2/a').click()
역시나 selenium사용시 가장 첫 부분에 필요한 코드이다. 만일 이런식으로 코드를 작성했는데 원하는 엘리먼트가 찾아지지 않거나 click이 되지 않는다면? 둘째줄의 webdriver.Chrome 를 적어주었는지 확인하자. 아니라면 지금 겪는 오류는 그것 때문일 것이다. 자세한 내용은 아래 포스팅을 참고해서 chrome driver 부터 설치하자.
꿀팁 1 맥 사용자의 경우 경로는 cmd창에 해당 파일을 drag&drop하면 쉽게 얻을 수 있다.
꿀팁2 경로 끝 자락에 /chromedriver 라고 이름까지 제대로 넣어줘야한다.
https://beomi.github.io/2017/02/27/HowToMakeWebCrawler-With-Selenium/
from selenium import webdriver driver = webdriver.Chrome('/Users/Desktop/project/chromedriver') url = 'https://youngseokim.tistory.com' driver.get(url) driver.implicitly_wait(3) driver.find_element_by_xpath('/html/body/div[12]/div[2]/div/h2/a').click() driver.find_element_by_xpath('/html/body/div[0]/h1/a').click()
이런식으로 웹사이트 상 하이퍼링크를 타고 세부 페이지로 넘어가는 경우에 여러 요소를 연속적으로 클릭하고 싶을 수 있다. 하지만 두번째 페이지부터 원하는대로 넘어가지 않는게 육안으로 보이면서 NoSuchElementException가 발생할 수 있다. 이는 웹사이트가 로딩이 되기도 전에 다음 작업을 수행하려고 할때 발생하는 오류이다. 매번 작업을 수행하기 전에 적절한 시간적 버퍼를 주어야한다. 코드는 다음과 같다.
import time driver.find_element_by_xpath('/html/body/div[12]/div[2]/div/h2/a').click() time.sleep(3)
time.sleep(3) 의 의미는 3초간 코드 실행을 멈추라는 것이다. 괄호 안은 초 단위이다.
첨언하자면 try except 구문으로 오류를 해결하라는 조언들이 인터넷에 많은데 이것은 단순히 에러가 발생할시 넘어가라는 미봉책일 뿐이므로, 로딩 시간 오류가 아니라는 확신이 있을때 본인의 필요에 맞게 써야한다.
그 외에도 selenium을 활용한 동적 크롤링 시 발생할 수 있는 오류는 다음과 같은 것들이 있다.
RemoteDisconnected
ProtocolError
ConnectionRefusedError
MaxRetryError
위의 오류들은 구글링을 해도 해답이 잘 나오지 않는 경우가 많은데 대부분은 크롤링하고자하는 웹사이트가 과도한 서버 부하를 막고자 크롤링 봇을 감지하고 막는 경우로 생각해 볼 수 있다. 모두 time.sleep(30) 등 꽤 긴 시간적 버퍼를 둠으로써 해결할 수 있다.
+(추가)
이건 그냥 돌려보면서 느낀건데 크롬 창이 계속 뜨면 불편할 뿐 아니라 에러가 평소보다 많이 나는걸 발견했다. 지속적인 크롤링을 위해서는 headless chrome을 이용해야하고 아래 블로그에 자세한 설명이 나와있다.
https://beomi.github.io/2017/09/28/HowToMakeWebCrawler-Headless-Chrome/