WEB

[Python] 파이썬으로 웹 스크래핑하기

프라이D 2022. 6. 30. 21:03

스파르타 코딩클럽 웹개발 종합반 강의를 수강하며 공부한 웹스크래핑 내용을 정리해 보았다.

웹 크롤링 vs 웹 스크래핑

웹 크롤링은 url을 탐색해 반복적으로 링크를 찾아 가져오는 과정이다. 웹 스크래핑은 특정 웹페이지의 데이터를 추출하는 것이다. 정보를 수집한다는 공통점이 있지만, 크롤링의 경우 특정 웹페이지를 타겟으로 하지 않고, 또한 데이터 중복 방지를 위해 색인을 남기기 때문에, 웹 인덱싱이라고도 한다. 

필요 패키지 설치

가상 환경 폴더에 필요 패키지를 설치해준다.

# requests 패키지 : HTTP 요청을 위한 라이브러리이다.
pip install requests

# BeautifulSoup : requests를 통해 가져온 html을 파싱하여 의미있는 데이터를 추출한다.
pip install bs4

# 추가로 VS code 에서 사용할 수 있는 파이썬 code formatter를 설치해주었다.
pip install -U autopep8

requests 와 BeautifulSoup을 활용한 스크래핑

기본 코드 프레임은 아래와 같다.

import requests # requests 모듈 임포트
from bs4 import BeautifulSoup # bs4 모듈 내 BeautifulSoup 클래스 임포트

# 타겟 url
url = 'https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829'
# 웹 서버에 get 요청
data = requests.get(url)
# 응답코드가 200(정상)이 아닐 시 예외 발생
data.raise_for_status() 
# 응답 객체의 text 속성, 내장 html.parser를 사용해 BeautifulSoup 객체화
soup = BeautifulSoup(data.text, 'html.parser')

+ 웹스크래핑시 웹 서버가 가짜 로봇 클라이언트의 접근을 막기 위해 요청을 거부할 수 있는데, 이 때 우리가 사람이라는 것을 서버에 알려주기 위해서 사용자 에이전트(user agent) 정보를 요청과 함께 전달할 수 있다.

# 나의 user agent 정보가 담긴 headers 객체를 만든다.
headers = {'User-Agent': 'WhatIsMyBrowser.com에 접속해 여기에 들어갈 내용을 찾을 수 있다.'}
    
# url과 함께 headers를 전달하여 get 요청을 보낸다.    
data = requests.get(url, headers=headers)

WhatIsMyBrowser < 이 링크를 클릭해 user agent 정보를 확인할 수 있다.

 

BeatifulSoup 객체화 된 html에서 원하는 데이터는 다음과 같이 가져온다.

# copy selector를 통해 추출한 selector 정보
# #old_content > table > tbody > tr:nth-child(2) > td.title > div > a

# 모든 데이터가 공통으로 가진 부분을 .select로 전체 선택한다.
movies = soup.select('#old_content > table > tbody > tr')

# 그리고 반복문 내에서 필요한 부분의 selector를 select_one 메서드로 각각 지정하여 할당한다. 
# .text 혹은 ['속성'] 으로 원하는 부분을 추출할 수 있다.
for movie in movies:
    a = movie.select_one('td.title > div > a')
    if a is not None:
        title = a.text
        rank = movie.select_one('td > img')['alt']
        score = movie.select_one('td.point').text
        doc = {
            'rank': rank,
            'title': title,
            'score': score
        }

Copy selector

select 메서드 대신 find 메서드를 이용해 태그로 추출하는 방법도 있다. 

스크래핑 결과 DB 저장

위 코드에서 스크래핑한 결과를 출력하면 아래와 같다. 

이런 데이터를 저장하고 활용할 수 있도록 DB 에 저장하고자 한다. 활용할 DB는 NoSQL DB 인 mongoDB 이다.

  • NoSQL  : Nol Only SQL 전통적인 관계형 데이터베이스보다 융통성 있는 데이터 모델을 사용해 유연한 대처가 가능하다.

mongoDB Atlas에서 계정을 생성해 mongoDB 클라우드 서비스를 이용할 수 있다. 

 

db 연결을 위해 아래 패키지를 설치한다.

pip install pymongo dnspython

pymongo에서 활용할 수 있는 코드는 다음과 같다.

# 전체 검색
# 모든 users 콜렉션의 요소 
# = 리스트(찾을 db.찾을 컬렉션.찾기({조건 1}, {조건 2 - db가 자동생성한 _id를 제외한 값}))
all_users = list(db.users.find({}, {'_id': False}))

for user in all_users:
    print(user)

# 특정 조건 하나만 검색
user = db.users.find_one({'name': 'kenny'}, {'_id': False})
print(user)

# 수정
# 찾을 db.찾을 컬렉션.하나를 업데이트
# ({조건}, {앞 조건을 set 하라: {적용할 내용}})
db.users.update_one({'name': 'kenny'}, {'$set': {'age': 19}})

# 삭제
db.users.delete_one({'name': 'kenny'})

전체 코드

from pymongo import MongoClient
import requests 
from bs4 import BeautifulSoup


url = 'https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829'
headers = {'User-Agent': 'WhatIsMyBrowser.com에 접속해 여기에 들어갈 내용을 찾을 수 있다.'}
data = requests.get(url, headers=headers)
data.raise_for_status() 
soup = BeautifulSoup(data.text, 'html.parser')

# DB 연결
client = MongoClient(
    'mongoDB에서 connectYourApplication을 선택하면 입력 코드가 나온다.')
db = client.dbname

movies = soup.select(
    '#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    if a is not None:
        title = a.text
        rank = movie.select_one('td > img')['alt']
        score = movie.select_one('td.point').text
        doc = {
            'rank': rank,
            'title': title,
            'score': score
        }
        
        #db 에 collection-name으로 doc을 insert_one 한다.
        db.collection-name.insert_one(doc)

이렇게 db에 저장을 마치면 mongoDB atlas에서 아래와 같이 확인할 수 있다.

 

참고 자료

https://www.snugarchive.com/blog/python-web-scraping/