오늘은 python library beautifulSoup를 이용하여 필요한 정보를 crawling 후, db에 저장하는 방법에 대해 적어보겠습니다.
python : 3.8
mysql : 8.0
1. 필요한 라이브러리 install
pip install requests
pip install beautifulsoup4
pip install pymysql
requests : http 요청처리를 위해 사용하는 모듈
beautifulsoup4 : html 및 xml 문서 구문 분석을위한 Python 패키지
pymysql : python과 mysql을 이어주는 패키지
2. html 크롤링하기
import requests | |
from bs4 import BeautifulSoup | |
url = "https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=cur&date=20200803" # 영화+평점 페이지 | |
webpage = requests.get(url) # url 객체 저장 | |
soup = BeautifulSoup(webpage.content, "html.parser") # 해당 url의 html 가져옴 |
저는 영화와 평점이 있는 웹페이지 url을 선언해주고, 해당 웹페이지의 html을 가져왔습니다. 실제로 print(soup)해보면, 해당웹페이지에서 f12번을 누르면 볼 수 있는 html파일이 프린트 됩니다.
몇가지 조건을 넣어서 필요한 것들만 가져올 수 있는데, 예시코드는 여기 를 참고해주세요
3. 가져올 정보 위치 찾기
저는 summer_intern이라는 db를 생성하고, test_crawling이라는 테이블을 만들어주었습니다. attribute에는 pk, movie(varchar(30)), poin(varchar(10)) 을 넣어주었습니다.

제가 가지고 와야 할 정보는 영화제목과 평점 입니다. f12번을 누르면 html 소스가 나타나는데, 영화검색 버튼 오른쪽에 노란색 하이라이트 친 부분을 클릭 후 '가버나움' 이라는 영화제목을 클릭하면 해당 소스가 어느부분인지 회색 블락으로 표시됩니다. 잘 살펴보면 div 태그에 class 이름은 tit5라고 지정되어있습니다. '위대한 쇼맨'을 클릭해도 div태그에 class 이름은 tit5입니다. 따라서 영화제목들은 <div class='tit5'> 로 가져올 수있습니다.
마찬가지로 평점은 td태그에 point 라는 이름으로 지정되어있습니다.
title_n = soup.find_all('div', 'tit5') | |
point_n = soup.find_all('td', 'point') | |
movie_name = [soup.find_all('div', 'tit5')[n].a.string for n in range(0, len(title_n))] | |
movie_point = [soup.find_all('td', 'point')[n].string for n in range(0, len(title_n))] |
title_n은 div태그의 class 가 tit5인 요소를 모두 가져옵니다. (point_n도 마찬가지)
movie_name은 해당 요소에서 진짜 영화제목을 리스트에 저장하는 코드입니다.
title_n과 point_n을 출력해보면(보기쉽게 3개만 출력해보았습니다)
print(title_n[:3]) | |
print(len(title_n)) | |
print(point_n[:3]) | |
print(len(point_n)) | |
[<div class="tit5"> | |
<a href="/movie/bi/mi/basic.nhn?code=174830" title="가버나움">가버나움</a> | |
</div>, <div class="tit5"> | |
<a href="/movie/bi/mi/basic.nhn?code=106360" title="위대한 쇼맨">위대한 쇼맨</a> | |
</div>, <div class="tit5"> | |
<a href="/movie/bi/mi/basic.nhn?code=163788" title="알라딘">알라딘</a> | |
</div>] | |
50 | |
[<td class="point">9.59</td>, <td class="point">9.40</td>, <td class="point">9.38</td>] | |
50 |
이렇게 나옵니다. 영화제목은 그중에서도 a태그 안에 있는것을 확인할 수 있습니다.
그래서 movie_name list를 만들 때, div tag와 class가 tit5 인것을 find_all 로 모두 찾은 후, .a 로 a태그만 걸러내고, 그것을 string형식으로 바꿔줍니다.(영화제목 수 만큼-> len(title_n), title_n은 해당 웹페이지에서 모든영화제목을 가져온 리스트입니다)
point는 td태그에 있으므로 그냥 .string으로만 했습니다.
movie_name, movie_point를 출력해보면,
['가버나움', '위대한 쇼맨', '알라딘', '소년시절의 너', '다크 나이트', '시네마 천국', '패왕별희 디 오리지널', '우리들', '피아니스트의 전설', '바람과 함께 사라지다', '톰보이', '스
타 이즈 본', '샤인', '미스비헤이비어', '타오르는 여인의 초상', '미져리', '안녕, 나의 소울메이트', '온워드: 단 하루의 기적', '미션', '시티 오브 갓', '미녀와 야수', '소공녀', '벌
새', '베스트 오퍼', '카메라를 멈추면 안 돼!', '트로이', '라라랜드', '플라이', '찬실이는 복도 많지', '내일을 위한 시간', '헤이트풀8', '캐리', '울프 콜', '소리꾼', '다가오는 것들', '카페 벨에포크', '밤쉘: 세상을 바꾼 폭탄선언', '원 데이', '로마 위드 러브', '클라우즈 오브 실스마리아', '몽상가들', '야구소녀', '존 윅', '아들', '결백', '호우시절', '조디악',
'유령선', '반도', '레이니 데이 인 뉴욕']
['9.59', '9.40', '9.38', '9.36', '9.34', '9.31', '9.31', '9.25', '9.25', '9.24', '9.22', '9.18', '9.08', '9.05', '9.05', '9.02', '8.98', '8.97', '8.92', '8.84', '8.78', '8.77',
'8.76', '8.64', '8.64', '8.62', '8.60', '8.60', '8.60', '8.54', '8.45', '8.43', '8.41', '8.35', '8.33', '8.32', '8.25', '8.22', '8.18', '8.17', '8.11', '8.08', '7.95', '7.86', '7.61', '7.38', '7.38', '6.31', '5.97', '5.35']
이렇게 필요한 것만 리스트에 잘 저장이 되어있습니다.
5. db에 연결하기
import pymysql | |
from db_setting import db | |
conn = pymysql.connect(host=db['host'], user=db['user'], password=db['password'], db=db['db'], charset=db['charset']) | |
curs = conn.cursor(pymysql.cursors.DictCursor) | |
# db_setting.py | |
db = {'host'=[host], ...} |
소스를 github에 올리는데, db정보는 올리면 안되기때문에 같은폴더에 db_setting.py 파일을 만들고, 파일안에 db 딕셔너리를 만들어 주었습니다. 그리고 이 파일에서 import 를 해주었습니다. 그리고 db_setting.py 는 .gitignore에 추가해주었습니다. 각자의 db정보를 넣어주시면 되겠습니다.
for title,point in zip(movie_name, movie_point): | |
sql = "INSERT INTO test_crawling (movie, point) VALUES (%s,%s)" | |
val = (title,point) | |
curs.execute(sql, val) | |
conn.commit() | |
conn.close() |
zip으로 영화제목과 평점을 튜플로 묶어준 것에서 title과 point하나씩을 뽑아서 val에 넣어줍니다. sql문은 insert문으로 짜줍니다. INSERT INTO [table_name] (column_1, column_2) VALUES (value_1, value_2)
commit 하고, connection을 닫아줍니다.
db에 들어가서 확인해보면 데이터가 저장되어있는걸 확인할 수 있습니다.
<전체코드>
import requests | |
from bs4 import BeautifulSoup | |
from db_setting import db | |
url = "https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=cur&date=20200803" # 영화+평점 페이지 | |
webpage = requests.get(url) | |
soup = BeautifulSoup(webpage.content, "html.parser") | |
# print(soup) 해당 web page의 html 가져온다 | |
# print(soup.p) 첫번째 p태그 가져옴 | |
# 등등 필요한 정보만 가져오는 예시 코드 : http://hleecaster.com/python-web-crawling-with-beautifulsoup/ | |
title_n = soup.find_all('div', 'tit5') | |
point_n = soup.find_all('td', 'point') | |
print(title_n[:3]) | |
print(len(title_n)) | |
print(point_n[:3]) | |
print(len(point_n)) | |
movie_name = [soup.find_all('div', 'tit5')[n].a.string for n in range(0, len(title_n))] | |
movie_point = [soup.find_all('td', 'point')[n].string for n in range(0, len(title_n))] | |
print(movie_name) | |
print(movie_point) | |
import pymysql | |
conn = pymysql.connect(host=db['host'], user=db['user'], password=db['password'], db=db['db'], charset=db['charset']) | |
curs = conn.cursor(pymysql.cursors.DictCursor) | |
for title,point in zip(movie_name, movie_point): | |
sql = "INSERT INTO test_crawling (movie, point) VALUES (%s,%s)" | |
val = (title,point) | |
curs.execute(sql, val) | |
conn.commit() | |
conn.close() | |
'개발' 카테고리의 다른 글
[노마드코더]인스타 클론코딩 사전 지식 쌓기 (0) | 2021.03.07 |
---|---|
ubuntu crontab 설정하기 (0) | 2020.09.25 |
ec2 ppk 파일 없이 접속하기 (0) | 2020.08.02 |
라즈베리파이 기본설정 (0) | 2020.07.23 |