Week3_2 파이썬으로 데이터 수집하기
네이버 뉴스 기사 수집하기
안티크롤링과 회피방법
데이터 수집을 하다보면 이 데이터수집을 막아놓은 홈페이지가 있다.
웹 데이터 자체는 모두에게 공개된 데이터이지만 데이터를 각 기업이 핵심적인 가치로 사용하는 경우, 뺏기고싶지 않기 때문.
사람인의 경우 잡코리아의 데이터를 무단 크롤링하여 법적 제재를 받은 경우가 존재한다.
따라서 데이터 수집을 할 때에 데이터를 수집하는 것 자체가 위법은 아니지만, 이를 불공정한 방법으로 사용하는 것은 위법이 될 수 있다.
이렇게 데이터 크롤링을 막아놓은 기술이나 정책을 안티 크롤링
이라고 한다. 때문에 원하는 데이터를 얻지 못하는 경우가 있다. 따라서 간단한 데이터 크롤링 회피 방법이 있다.
기본적으로 웹브라우저에서 어떤 홈페이지에 들어갈때, 홈페이지가 웹브라우저에 대한 정보도 가지고 있다. 우리가 어떤 데이터를 요청하면 크롬/파이어폭스에서 데이터를 요청한 것을 인식하고 데이터를 제공한다. 하지만 데이터 수집기를 만든 것 처럼 파이썬 코드에서 데이터를 요청하면 크롬/파이어폭스와 같은 웹브라우저에서 접속한 것이 아니기 때문에 거절이 된다. 따라서 이를 회피하기 위해서 다음과 같은 코드를 사용한다.
# get함수에 headers라는 옵션을 추가한다.
raw = requests.get("URL",
headers = {"User-Agent" : "Mozilla/5.0"})
Mozilla 5.0은 웹브라우저를 만들기 위해 사용하는 기본적인 엔진이다. 이를 넣어줌으로써 파이썬에서 데이터를 요청했을 때 서버를 헷갈리게 할 수 있다. 따라서 우리가 원하는 데이터를 얻는 것이 가능.
get함수에서 headers에 들어갈 것은 다음 사이트에서 참고
실제로 크롬의 User-Agent값은 버전별로 다르고 다양하다.
안티 크롤링 규칙을 엄격하게 사용하는 홈페이지의 경우 헤더값에 이를 다 넣어줘야하는 경우가 있다.
> 중요 소스
import requests
from bs4 import BeautifulSoup
raw = requests.get("URL",
headers = {"User-Agent" : "Mozilla/5.0"})
html = BeautifulSoup(raw.text, 'html.parser')
이 소스는 계속해서 사용할 것이기 때문에, 외우든지 복붙을 하면 좋다.
선택자 심화와 수집기 완성하기
네이버 검색엔진에서 '코알라'를 검색한 후, '뉴스'를 클릭한 부분의 링크의 기사들을 크롤링해보자
다음과 같은 순서로 데이터 수집기를 완성할 것이다.
# 1. 컨테이너 수집
# 2. 기사별 데이터 수집(제목, 언론사)
# 3. 수집반복(컨테이너)
그럼 검색 결과에 대한 선택자를 찾아보자.
# 0. 컨테이너 ul.type01 >li
# 1. 기사제목 ul.type01 >li a._sp_each_title
# 2. 언론사 ul.type01 >li span._sp_each_source
* 선택자는 다르게 나올 수 있다.
브라우저의 개발자 모드에서 command + f(윈도우는 ctrl + f)를 하였을 때
원하는 부분을 가리키기만 하면 된다.
1. 컨테이너 수집과 2. 기사별 데이터 수집
import requests
from bs4 import BeautifulSoup
raw = requests.get("URL",
headers = {"User-Agent" : "Mozilla/5.0"})
html = BeautifulSoup(raw.text, 'html.parser')
# 1. 컨테이너 수집
articles = html.select("ul.type01 > li")
# select는 선택자에 해당하는 모든 데이터를 리스트 형식으로 저장하는 함수이다.
# 2. 기사별 데이터 수집(제목, 언론사)
title = articles[0].select_one("ul.type01 > li a._sp_each_title").text
source = articles[0].select_one("ul.type01 >li span._sp_each_source").text
# .text는 가져온 raw데이터를 소스코드로 보기 위함.
print(title, source)
이 코드를 실행하면 첫번째 기사에 대한 정보가 크롤링될 것이다.
이제 반복문
을 활용하여 10개의 기사에 대한 정보를 모두 크롤링해보자.
3. 수집반복(컨테이너)
import requests
from bs4 import BeautifulSoup
# 링크는 네이버 검색창에 '코알라'를 검색하고 '뉴스'부분을 클릭한 사이트의 링크
raw = requests.get("https://search.naver.com/search.naver?where=news&sm=tab_jum&query=%EC%BD%94%EC%95%8C%EB%9D%BC",
headers = {"User-Agent" : "Mozilla/5.0"})
html = BeautifulSoup(raw.text, 'html.parser')
# 1. 컨테이너 수집
articles = html.select("ul.type01 > li")
# select는 선택자에 해당하는 모든 데이터를 리스트 형식으로 저장하는 함수이다.
# 2. 기사별 데이터 수집(제목, 언론사)
for ar in articles:
title = ar.select_one("ul.type01 > li a._sp_each_title").text
source = ar.select_one("ul.type01 > li span._sp_each_source").text
# .text는 가져온 raw데이터를 소스코드로 보기 위함.
print(title, source, sep = " // ")
# 기사 제목과 source가 " // "를 통해 구분된다.
여러 페이지에서 기사 수집하기
URL과 요청값 이해하기
여러페이지에 걸쳐서 데이터를 수집하는 방법에 대해 알아보자. 위의 소스코드의 경우 한페이지의 데이터만 수집할 수 있기에 10개의 기사만 수집되었다.
우리가 고작 10개의 데이터를 크롤링하자고 수집기를 만드는 것이라면 수집기를 만드는 것 보다 복붙하는 것이 더 효과적일 것이다.
근데 그러면 너무나 멋이 없지 않은가? (^-^)
그러니 이제 여러 페이지를 걸쳐 크롤링하는 것에 대하여 알아보자.
여러 페이지에서 데이터를 수집하기 위해서는 우선
URL주소
에 주목해보자.
검색창을 제어할 수 있는 요청값들에 대한 정보가 모두 URL에 담겨있다.
다음은 네이버 검색창에서 '코알라'를 검색한 후, '뉴스' 카테고리를 클릭한 페이지의 1, 2, 3페이지의 URL이다.
보통 URL의 ?뒤가 요청값이며 이는 &로 구분된다.
각 URL의 start부분이 10을 단위로 등차수열임을 알 수 있다. (1, 11, 21, 31, 41, ,,,)
이와 같은 규칙을 통해 네이버의 검색엔진 페이지는 1, 11, 21, 31, 41,,, 의 규칙을 가지는 것을 알아내었다. (요청값의 규칙은 웹페이지마다 다르다. 따라서 여러 페이지를 클릭하면서 규칙을 알아내자.)
import requests
from bs4 import BeautifulSoup
for page in range(1, 100, 10):
raw = requests.get("https://search.naver.com/search.naver?&where=news&query=%EC%BD%94%EC%95%8C%EB%9D%BC&sm=tab_pge&sort=0&photo=0&field=0&reporter_article=&pd=0&ds=&de=&docid=&nso=so:r,p:all,a:all&mynews=0&cluster_rank=24&start="+str(page)+"&refresh_start=0",
headers = {"User-Agent" : "Mozilla/5.0"})
html = BeautifulSoup(raw.text, 'html.parser')
# 1. 컨테이너 수집
articles = html.select("ul.type01 > li")
# select는 선택자에 해당하는 모든 데이터를 리스트 형식으로 저장하는 함수이다.
# 2. 기사별 데이터 수집(제목, 언론사)
for ar in articles:
title = ar.select_one("ul.type01 > li a._sp_each_title").text
source = ar.select_one("ul.type01 > li span._sp_each_source").text
# .text는 가져온 raw데이터를 소스코드로 보기 위함.
print(title, source, sep = " // ")
# 기사 제목과 source가 " // "를 통해 구분된다.
print("="*50) # 페이지가 넘어갈때마다 구분해주기 위한 구분선
위의 소스는 두 가지의 반복문을 가지고 있다.
첫번째의 반복문을 통해 페이지의 숫자를 바꿔가며 데이터 요청을 반복하고 수집하며,
두번째의 반복문을 통해 페이지 내의 10개 기사에 대한 정보를 요청하고 반복하여 수집한다.
출처
코알라: https://coalastudy.com
데이터수집 web 공개자료: https://book.coalastudy.com/data_crawling/
'Data_Analysis' 카테고리의 다른 글
[코알라univ]4. 데이터를 저장하는 방법 (0) | 2019.10.30 |
---|---|
[코알라univ]3_3. 파이썬으로 데이터 수집하기 (0) | 2019.10.29 |
[코알라univ]3_1. 파이썬으로 데이터 수집하기 (0) | 2019.10.14 |
[코알라univ]2. 데이터수집을 위한 기초 파이썬 (0) | 2019.10.10 |
[코알라univ]1. 웹페이지의 이해 (0) | 2019.10.02 |