웹/크롤링

[BeautifulSoup] #2 파이썬 웹 크롤링 네이버 오류 해결 방법

호무비 2022. 2. 12. 23:49
반응형

오늘은 파이썬으로 네이버 웹 크롤링 중 발생하는 오류 해결 방법에 대해 알아보겠습니다. BeautifulSoup를 활용한 강의의 연장선이지만, 파이썬 선에서 발생하는 문제입니다.

 

일반적으로 웹 크롤링을 한다고 하면, 개인 사이트보다는 네이버나 구글, 다음 등에서 제공하는 특정 정보를 얻기 위한 경우가 많습니다.

 

오늘 소개할 내용은 그중 하나인 네이버 웹 크롤링 시 많이 발생하는 문제인데요, 지금부터 설명하도록 하겠습니다.


문제 상황

 

아래는 간단하게 네이버 연합뉴스 내용을 크롤링하도록 한 코드입니다. (다음번에 자세히 소개할 예정입니다.)

 

import requests
from bs4 import BeautifulSoup

# main
if __name__ == "__main__":
    inputURL = "https://news.naver.com/main/list.naver?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y"
    response = requests.get(inputURL)
    beautifulSoup = BeautifulSoup(response.content, "html.parser")
    print(beautifulSoup.title.string)
    print(beautifulSoup.find("dl", attrs={"class":"type04"}).get_text())
    print(beautifulSoup.find("ul", attrs={"class":"type02"}).get_text())

 

다음과 같이 동작하지 않고 이상한 오류가 발생하는 것을 확인할 수 있습니다.

 

 

지난번 티스토리 블로그의 경우 잘 동작했는데, 왜 이번에는 오류가 발생한 것일까요?

 

방금 본 오류를 잘 살펴보면 다음과 같은 내용을 확인할 수 있습니다.

 

requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

 

ConnectionError 가 발생했으므로, 뭔가 연결에 문제가 생겼다는 것을 알 수 있습니다. 내용을 더 읽어보면 연결이 중단되었고, response가 없다는 내용을 확인할 수 있습니다.

 

여기에서 중요한 점은, 평범하게 네이버 연합뉴스 페이지에 접속할 경우 문제없이 동작한다는 점입니다. 직접 사용할 때는 response를 전달하지만 크롤링 할 때는 동작하지 않는다는 것은 한 가지 이유를 생각해 볼 수 있습니다.

 

바로 네이버 측에서 크롤링하지 못하도록 제약을 걸어놓은 것인데요, 이를 해결하기 위해서는 http 헤더에 대해 알아야 합니다.


http 헤더(header)란?

 

http 헤더는 클라이언트와 서버가 통신할 때 함께 전달하는 부가 정보로 날짜, 인코딩 정보, 유저 정보 등 다양한 내용을 담고 있습니다.

 

우리는 이 헤더의 내용 중 User-Agent 부분을 설정해 줄 예정입니다. User-Agent에는 운영체제, 소프트웨어 버전, 소프트웨어 유형 등 여러 내용이 포함되어 있습니다.

 

정상적인 방법으로 웹 페이지에 접속하게 되면 다음과 같은 User-Agent 내용을 확인할 수 있습니다. (data-useragent 부분)

 

네이버 메인 페이지 소스 코드

 

그러나, 웹 크롤러 등과 같이 봇을 이용하게 되면 이 User-Agent 내용이 달라집니다. 이를 기준으로 네이버가 정상적이지 않은 접근이라고 판단하게 되면, 위와 같은 문제가 발생하는 것입니다.

 

requests 관련 문서를 보면 다음과 같이 헤더를 설정하는 내용을 확인할 수 있습니다.

 

https://docs.python-requests.org/en/master/user/quickstart/#custom-headers

 

지난번 소개했던 코드에서는 헤더를 설정하지 않았는데, 앞서 보았듯 기존 헤더로는 네이버가 일반 유저로 인식하지 않으므로, 헤더를 별도로 지정해 주어야 합니다.

 

헤더의 내용은 http://www.useragentstring.com/pages/useragentstring.php 를 참고하여 작성할 수 있습니다.

 

해당 웹사이트에 접속하면 아래와 같이 본인이 원하는 User Agent를 찾아볼 수 있습니다. 아래에 대표적으로 우리가 사용하게 될 크롬, 엣지, 파이어폭스를 표시해두었습니다.

 

 

예를 들어 크롬의 User Agent가 궁금하다면 원하는 버전의 내용을 확인하고 복사해주면 됩니다.

 


request에 User-Agent header 내용 추가하기

 

이제 헤더를 추가하여 request를 보내보겠습니다.

 

헤더는 딕셔너리 형식으로 지정하여 설정해주면 됩니다. User-Agent가 Key가 되고, 위에서 얻은 그 값이 value입니다. 예를 들어 저의 경우에는 다음과 같이 설정해주었습니다.

 

headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"}

 

여기에 다음과 같이 headers=[헤더 변수명] 을 get 메소드의 파라미터로 전달해주면 설정한 헤더로 request를 수행하게 됩니다.

 

requests.get(url, headers=headers)

 

이제 아까 실패했던 연합뉴스 크롤링을 다시 진행해 보겠습니다. 처음 코드와 거의 동일하지만 헤더 내용만 하나 추가되었습니다.

 

import requests
from bs4 import BeautifulSoup

headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"}

# main
if __name__ == "__main__":
    inputURL = "https://news.naver.com/main/list.naver?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y"
    response = requests.get(inputURL, headers=headers)
    beautifulSoup = BeautifulSoup(response.content, "html.parser")
    print(beautifulSoup.title.string)
    print(beautifulSoup.find("dl", attrs={"class":"type04"}).get_text())
    print(beautifulSoup.find("ul", attrs={"class":"type02"}).get_text())

 

아래와 같이 잘 동작하는 것을 확인할 수 있습니다.

 


파이썬에서 네이버 크롤링 오류 해결 방법에 대해 알아보았습니다. 네이버와 같이 웹 크롤링에 제약을 두는 경우가 종종 있으니 헤더를 기본적으로 설정하고 작업하는 것도 도움이 될 수 있습니다. 잘 활용해서 크롤링하시기 바랍니다.

 

직접 조사해서 작성하는 글이다 보니 일부 정확하지 않은 정보가 포함되어 있을 수 있습니다.

궁금한 사항이나 잘못된 내용이 있으면 댓글로 알려주세요~

구독과 좋아요 환영합니다!

 

반응형