Pandas의 read_html( ) 함수는 특정 URL의 Table 정보를 크롤링 합니다. 예제로 국내 프로야구 선수 타율 정보를 Pandas로 가져와 조회하는 예제를 블로깅 했었습니다.
https://blog.naver.com/sehyunfa/221770769064
특정 사이트의 경우, read_html( )을 거부하고 404 Forbdden 응답하는 경우가 있습니다. 사이트 관리자가 크롤링을 수행하는 Pandas와 같은 크롤러(crawler)와 봇(bot)을 막았거나, 일반적인 브라우저가 아닌 접속에 대해서는 응답하지 않도록 설계한 경우입니다.
https://www.worldometers.info/coronavirus/ 페이지는 실시간으로 국가별 코로나 감염자 수 등의 정보를 제공하는 유명한 사이트입니다. 매일매일 업데이트됩니다.
아래와 같이 단 3 줄로 크롤링이 가능했던 국가 정보가 언제부턴가 크롤링을 막아서 403 응답을 하더군요. 보통 이런 경우 회피를 위해서 user-agent를 브라우저와 비슷하고 변조하거나, referer 헤더와 같이 일반적인 브라우저가 가진 요청 헤더들을 추가하여 브라우저처럼 보이도록 합니다.
Pandas의 Github을 찾아보면, 이와 같은 상황에서 Pandas 요청을 위장하기 위한 User-Agent 변조 기능이 없고 앞으로도 수정 계획이 없다고 나옵니다. https://github.com/pandas-dev/pandas/issues/4927
대안으로 제시된 방법은 urllib.request 라이브러리를 사용하여 요청 헤더에 일반적인 브라우저가 가지고 있는 User-Agent 헤더 값을 넣어 크롤링을 수행하고, 그 값을 Pandas의 read_html( )로 읽으라는 것입니다. 이 가이드에 맞게 소스 코드를 수정해보았습니다.
이제는 403 응답 없이 결과를 가져올 수 있습니다.
결과가 214 row와 12개 칼럼이기에 소스 코드를 좀 더 수정하여, Top 20 국가에 대해서 중요한 칼럼 값만 가져오도록 수정하였습니다.
import pandas as pd
import urllib.request as urllib
url = r'https://www.worldometers.info/coronavirus/'
#urllib.request로 오프너 생성
opener = urllib.build_opener()
#User-Agent값을 요청 헤더에 포함
opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
#크롤링 수행
response = opener.open(url)
#크롤링한 첫 번째 테이블을 table 변수에 저장
table = pd.read_html(response.read())[0]
#Top 20개 국가만 출력하기 위해 head값을 21로 지정
table = table.head(21)
#특정 칼럼값만을 조회하기 위해 데이터 프레임 설정
covidDf = pd.DataFrame(table, columns=['Country,Other', 'TotalCases', 'TotalDeaths', 'ActiveCases', 'TotalRecovered', 'Serious,Critical'])
#데이터 프레임 출력
print(covidDf)
출력 결과입니다.
<결과 화면, 한국은 금일 현재 18번째로 확진자가 많은 국가다..>
무엇보다 COVID-19 조심하세요~!