본문 바로가기

Computer Science/Crawling with Python

크롤링 기본

더보기

목차

1. 파이썬 오픈소스 패키지 사용

2. 파이썬으로 데이터 수집하기

3. 안티크롤링, 헤더값 추가하기

4. URL과 요청값 이해하기

 

 

1. 오픈소스 패키지

 

파이썬은 오픈소스 프로그래밍 언어로 누구나 사용, 수정, 재배포 할 수 있습니다.

파이썬이 강력한 이유는 개발자들이 파이썬을 통해 유용한 도구들을 개발해 놓았기 때문입니다.

 

ex) django - 장고는 파이썬으로 웹개발을 할 수 있는 패키지입니다. 인스타그램, 유튜브 등

ex) flask - 장고보다 가벼우나 숙련자가 사용하기 좋습니다. 핀터레스트

ex) pandas - 표 형태의 데이터를 쉽게 다룰 수 있는 패키지입니다. 데이터 수집, 분석에 자주 사용

ex) request - 웹상의 데이터를 가져올 수 있게 하는 패키지

ex) beautifulsoup4 - html 코드를 파싱하여 원하는 코드를 추출하게 하는 패키지

스마트폰에서 어플을 받듯, 파이썬에서는 PIP(Python Package Index)에서 원하는 외부 패키지들을 다운로드 받아 사용합니다.

이번 포스팅에서는 request와 beautifulsoup4를 이용하여 데이터를 수집, 분석해 보도록 하겠습니다.

 

2. 오픈소스 패키지 활용하기 : requests, bs4

 

수집목표 - 네이버 tv TOP 100 1~3위 영상의 1.제목 2. 채널명 3.조회수 4. 좋아요 수

데이터 수집기를 만들기 위해서는 request와 bs4를 불러와야 합니다. 이를 위해 import 명령어를 사용합니다.

 

import requests
from bs4 import BeautifulSoup

 

Beautifulsoup 4는 bs4라는 폴더안에 들어있고, 그 중 BeautifulSoup이라는 기능을 사용하겠다는 뜻입니다.

1. 웹에서 데이터 가져오기

 

import requests
from bs4 import BeautifulSoup

raw = requests.get("https://tv.naver.com/r/")
print(raw)

 

실행결과 - response[200]

get이라는 함수는 request 패키지가 가지고 있는 함수입니다. 가운데에 .을 찍어서 아용합니다. get 함수는 괄호 안의 URL 주소에 접속을 요청하여 여러가지 데이터를 받아오는 기능을 합니다. 실행결과로 나타다는 코드는 정상적으로 응답했다는 뜻의 코드입니다.

이때 print안의 코드를 raw.text로 바꾸면 소스코드가 출력됩니다.

get 함수를 사용하면 응답 성공 여부, 응답 시간, 쿠키 등 여러가지 데이터를 가져와서 저장합니다. .text를 추가하면 HTML 코드를 확인할 수 있습니다.

 

2. HTML 소스코드 파싱하기 - BeautifulSoup 사용하기

 

import requests
from bs4 import BeautifulSoup

raw = requests.get("https://tv.naver.com/r/")

html = BeautifulSoup(raw.text, "html.parser")
print(html)

 

html이라는 변수에 BeautifulSoup의 괄호 안에는 raw.text와 "html.parser"이 들어갑니다. 그리고 html을 출력했을 때 raw.text를 출력했을 때와 동일하게 소스코드가 출력됩니다.

그렇다면 BeautifulSoup의 역할은 무엇일까요?

BeautifulSoup 함수는 html소스코드를 태그 기준으로 파싱해주는 일을 합니다. 이 함수를 사용해줘야 선택자를 사용할 수 있습니다.

raw.text에 저장된 소스코드는 단순한 문자열일 뿐이므로 컴퓨터에게 ~태그의 데이터 찾아줘 라고 명령해도 이해할 수 없습니다.

이때 bs 함수를 씌워주면 소스코드를 태그 기준으로 잘라주어 데이터를 찾아낼 수 있습니다.

*파싱(Parsing) : 일련의 문자열을 유의미한 단위로 구분하는 것.

따라서 우리는 requests.get을 이용해서 소스코드를 저장하고, BeautifulSoup을 사용해서 html 파싱까지 완료하여 본격적으로 데이터를 수집할 수 있습니다.

 

3. 데이터 수집기 완성하기

 

#1. 컨테이너 수집

컨테이너 : div.inner

 

#2. 영상(컨테이너) 별 데이터 수집

제목 : div.inner dt.title

채널명 : div.inner dd.chn

재생수 : div.inner span.hit

좋아요 수 : div.inner span.like

파이썬으로 구현하기

 

import requests
from bs4 import BeautifulSoup

raw = requests.get("https://tv.naver.com/r/")
html = BeautifulSoup(raw.text, "html.parser")

# 1. 컨테이너 수집하기
container = html.select("div.inner")
print(container)

 

원하는 데이터를 선택하기 위해서 select 함수를 사용합니다. 함수의 괄호 안에 선택자를 넣어주면선택자가 가리키는 모든 데이터를 리스트 형식으로 저장해 줍니다. *select 함수는 BeautifulSoup4 에 포함된 함수이므로 html로 파싱한 소스코드가 들어있는 변수에 사용해주어야 합니다.

즉 1위 영상이 container[0] 2위 영상이 container[1] 3위 영상이 container[2]가 됩니다.

- 영상별 데이터 수집

 

# 제목 수집하기
title = container[0].select_one("dt.title")
print(title.text)

 

title이라는 변수 안에 container[0], 즉 1위 영상에 대한 제목을 담아 보겠습니다. 이때 select와 select_one함수의 차이는, select 함수가 괄호 안의 선택자에 해당하는 모든 데이터를 저장한다면, select_one은 해당하는 테이터 중 첫번째 데이터 하나만 저장하는 함수입니다. 데이터를 수집하려는 소스코드 안에 데이터가 하나 있다면 select 함수를 통해 1개짜리 리스트로 받는 것 보다 select_one 함수를 통해 데이터로 받는 것이 훨씬 효율적이기 때문입니다. (나중에 사용할 때 인덱싱을 할 필요가 없기 때문입니다.)

이때 title만 출력해보면 해당하는 소스코드 전체가 태그를 포함해 출력됩니다. 이때 .text를 추가해주면 텍스트 데이터만 얻어낼 수 있습니다.

또한 strip() 함수를 사용해 채널명, 재생수, 좋아요수를 수집하여 공백까지 삭제할 수 있습니다.

 

# 1. 컨테이너 수집하기
container = html.select("div.inner")
#print(container)

# 2. 영상 데이터 수집
title = container[0].select_one("dt.title")
chn = container[0].select_one("dd.chn")
hit = container[0].select_one("span.hit")
like = container[0].select_one("span.like")

# 수집 결과 출력 부분
print(title.text.strip())
print(chn.text.strip())
print(hit.text.strip())
print(like.text.strip())

 

실행 결과

[최초 공개] 차승원x유해진x손호준! 섬 주민 달랑 3명? 오순도순 섬 생활 대공개!!

삼시세끼 어촌편 5

재생 수279,945

좋아요 수1,827

- 수집 반복(컨테이너)

 

# 1. 컨테이너 수집하기
container = html.select("div.inner")
#print(container)

# 2. 영상 데이터 수집
for cont in container:
    title = cont.select_one("dt.title")
    chn = cont.select_one("dd.chn")
    hit = cont.select_one("span.hit")
    like = cont.select_one("span.like")

# 수집 결과 출력 부분
    print(title.text.strip())
    print(chn.text.strip())
    print(hit.text.strip())
    print(like.text.strip())

 

 

4. 안티 크롤링과 회피방법

 

1. 웹페이지에서 크롤링을 막는 안티 크롤링(Anti-Crawling)

크롤링 행위 자체는 불법이 아니지만 크롤링을 통해 수집한 데이터를 부정하게 사용하는 경우를 대비해 다양한 방법을 사용해서 데이터 수집을 방해하고 있습니다. 이러한 정책이나 기술을 안티 크롤링이라고 합니다.

2. 간단한 안티 크롤링 회피방법

웹서비스에 접속해서 데이터를 요청할때는 웹브라우저를 통해 데이터를 요청하고, 서버는 어디인지 확인한 다음 데이터를 돌려줍니다. 하지만 코드로 만든 데이터수집 프로그램을 통해서 데이터를 요청하는 경우에는 서버가 데이터를 요청한 웹브라우저의 정보를 확인할 수 없기 때문에 일부 웹서비스의 경우 요청한 데이터를 돌려주지 않습니다.

이때 아래와 같은 코드를 수정하면 안티 크롤링을 피해갈 수 있습니다.

 

import requests
from bs4 import BeautifulSoup

raw = request.get("URL", headers={'User-Agent':'Mozilla/5.0})
html = BeautifulSoup(raw.text, "html.parser")

 

headers를 통해 서버에 데이터를 요청하면서 웹브라우저에 대한 정보를 같이 전송하여 마치 웹브라우저를 통해 데이터를 요청하는 것 처럼 보이게 합니다.

 

# 다른 웹 브라우저의 User-Agent 값
Mozilla/5.0 (X11; Linux x86_64) 
AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/51.0.2704.103 Safari/537.36

 

 

5. 선택자 심화와 수집기 완성하기

 

컨테이너 ul.type01>li

제목 a._sp_each_title

언론사 span._sp_each_source

 

import requests
from bs4 import BeautifulSoup

raw = requests.get("https://search.naver.com/search.naver?where=news&sm=tab_jum&query=%EC%84%9C%EC%9A%B8%EC%8B%9C%EB%A6%BD%EB%8C%80%ED%95%99%EA%B5%90",
                  headers={'User-Agent':'Mozilla/5.0'})
html = BeautifulSoup(raw.text, "html.parser")


# 1. 컨테이너 수집
articles = html.select("ul.type01>li")

# 2. 데이터 수집
for ar in articles:
    title = ar.select_one("a._sp_each_title").text
    source = ar.select_one("span._sp_each_source").text

    print(title, source)
    print("="*50)

 

 

한 페이지에서 원하는 결과가 모두 나오지 않을때 ?

6. URL과 요청값 이해하기

URL의 구조는 홈페이지구조 + ? + 요청값으로 이루어져 있습니다.

'?'는 요청값과 홈페이지 주소를 연결해 줍니다. 물음표 뒤에 원하는 값을 넣어주면 요청 값에 따라 페이지에 표시되는 내용이 달리집니다.

search.naver.com/search.naver?where=image&query=파이썬

                                 검색 결과의 구분         검색어

네이버 뉴스의 경우 3가지 요청 값이 있음을 알아낼 수 있습니다.

search.naver.com/search.naver?where=news&sm=tab_jum&query=파이썬&start=11

                                           카테고리                      검색어          기사번호

 

네이버 기사에서 다음 페이지를 클릭하면 start 요청값이 start=1, start=11, start=21 순서로 변화합니다. 이를 이용하여 데이터 수집에 도전해봅시다.

1. URL 변화시키기

 

raw = requests.get("https://search.naver.com/search.naver?where=image&query=파이썬&start="+str(n)
                    , headers={'User-Agent':'Mozilla/5.0'})
html = BeautifulSoup(raw.text, "html.parser")

 

URL에 start 요청값을 추가해주고 n값을 추가할 때 str(n) 형태로 추가해줍니다. 문자열 더하기 방식을 사용하기 때문에 숫자를 문자로 변경햐주어야 하기 때문입니다.

 

start에 들어간 값을 1,11,21 순서로 반복시키려면 다음의 반복문을 만들면 됩니다.

 

for n in range(1,100,10):

 

import requests
from bs4 import BeautifulSoup

for n in range(1, 4):
    raw = requests.get("https://news.ycombinator.com/news?p="+str(n),
                      headers={'User-Agent':'Mozilla/5.0'})
    html = BeautifulSoup(raw.text, "html.parser")

    articles = html.select("tr.athing")

    # 2. 데이터 수집
    for ar in articles:
        title = ar.select_one("a.storylink").text
        rank = ar.select_one("span.rank").text
        source = ar.select_one("span.sitestr").text
        print(title, rank, source)
        print("="*50)

'Computer Science > Crawling with Python' 카테고리의 다른 글

웹페이지의 구성에 대하여  (0) 2020.11.20