안녕하세요.
저번 게시물에 이어 파이썬 영화 데이터 크롤링 2편 포스팅하겠습니다.
씨네21 크롤링
▶ 2차 크롤링 작업
- result_data01
2차까지는 Selenium으로 작업하였습니다.
result_data01에서 가져온 링크에 접속하여 별점 페이지로 넘어가고 end 버튼의 'href' 속성에 명시된 endpoint를 추출했습니다.
또한, 프로필 사진에 있는 image 링크도 추출했습니다.
이렇게 하나하나 셀레니움으로 버튼 클릭, css select를 하면 시간이 엄청나게 오래 걸린다는 단점이 있습니다.
당시 저는 크롤링에 익숙하지 않았고 자동화 코드를 만들 때 selenium만 사용해봤습니다.
( 지금 생각해보면 되게 비효율적인 코드입니다..)
만약 크롤링 작업을 하신다면, json이나 request를 사용하여 html 데이터를 추출하고 bs4 모듈로 파싱하는 방식을 적극 추천드립니다. ( 시간이 비교가 안됩니다.. )
▶ Python Code
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import pandas as pd
from bs4 import BeautifulSoup
from selenium.common.exceptions import NoSuchElementException
from tqdm import tqdm
import time
options = webdriver.ChromeOptions()
options.add_argument("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36") # 네트워크 설정
options.add_argument("lang=ko_KR") # 사이트 주언어
driver = webdriver.Chrome(ChromeDriverManager().install(),chrome_options=options)
# 2차 목표 : 01에서 가져온 사이트를 토대로 별점페이지수와 필자별 이미지 크롤링
df = pd.read_excel("/Users/mycelebs/PycharmProjects/Mycelebs/RealData/result_data01.xlsx")
kr_c_link = df.loc[:,"kr_c_link"]
data_list=[]
for i in tqdm(kr_c_link):
driver.get(f"{i}")
# 별점 페이지로 넘어가기 버튼 클릭
driver.find_element_by_css_selector('#content > div > div.floatL > div.tab_area1 > ul > li:nth-child(2)').click()
end = driver.find_element_by_css_selector('#write_view_review20_holder > div.pagination > a.btn_end').get_attribute('href')
# print(end)
image = driver.find_element_by_css_selector("#content > div > div.floatR > div.profile > img").get_attribute("src")
data = {"end":end, "image":image}
data_list.append(data)
driver.close()
result_df = pd.DataFrame(data_list, columns=['end','image'])
result_df.to_excel(f'/Users/mycelebs/PycharmProjects/Mycelebs/RealData/endpoint.xlsx', index=False)
▶ 3차 크롤링 작업
- result_data01 (수정)
kr_c_name | pre_code | endpoint |
박평식 | E20041252 | 898 |
이용철 | E20041291 | 433 |
황진미 | E20041338 | 273 |
이동진 | E20041283 | 224 |
김성훈 | E20041648 | 92 |
˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ |
앞서 추출한 데이터들에서 평론가 이름(kr_c_name), 코드(pre_code), 평점 영화 개수(endpoint)로 이루어진 result_data01 데이터 프레임을 수정했습니다.
마지막 작업은 requests(추출)와 BeautifulSoup(파싱) 모듈을 사용했습니다.
씨네21 사이트의 html 구조를 살펴보던 중 Network tab에서 info_review20 이라는 Request url을 발견했습니다.
Form Data를 살펴보니 pre_code와 p(endpoint)를 post해주면 될 것 같아서 result_data01에서
for문으로 payload {"pre_code": pre_code, "p": endpoint}를 request url에 post하여 html을 가져왔습니다.
가져온 html 구조를 보고 분석하여 제가 필요한 column을 soup으로 파싱하였습니다.
중간에 영화가 없는 경우가 있어 try ~ except문으로 예외 처리해주고 result_data02로 데이터 프레임화하여 작업을 마무리했습니다.
▶ Python Code
import requests
import pandas as pd
from bs4 import BeautifulSoup
from tqdm import tqdm
import time
import traceback
# 3차 목표 : 씨네21 평론가들의 영화평가코멘트, 별점, 해당 영화의 연도와 타이틀 크롤링
url ="http://www.cine21.com/db/writer/info_review20"
heades_data = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"}
df = pd.read_excel("C:/RealData/result_data01.xlsx")
sess = requests.Session()
data_list =[]
# numb = -1
for idx, row in tqdm(df.iterrows(), desc="돌리는중"):
pre_code = row['pre_code']
endpoint = row['endpoint']
kr_c_name = row['kr_c_name']
# numb = numb+1
for j in tqdm(range(1, endpoint+1), desc = "평론가 한 명의 영화평을 서치 중입니다~"):
# print(pre_code)
payload = {"pre_code": pre_code, "p":j}
res = sess.post(url, headers=heades_data, data=payload)
soup = BeautifulSoup(res.text, 'html.parser')
# print(soup)
for i in range(0, len(soup.find_all('p',{'class','mov_tit'}))):
try:
mov = soup.find_all('p', {'class':'mov_tit'})[i]
kr_mov_url = mov.find('a')['href']
# print(kr_mov_url)
kr_title =mov.find('a').text
# print(kr_title)
kr_year = soup.find_all('span', {"class":"year"})[i].text
# print(kr_year)
kr_comment = soup.find_all('p', {"class":"comment"})[i].text
# print(kr_comment)
kr_rating = soup.find_all('span', {'class':'num'})[i].text
# print(kr_rating)
except:
traceback.print_exc()
data = {"kr_c_name":kr_c_name, "pre_code":pre_code, "kr_mov_url": kr_mov_url,
"kr_title":kr_title, "kr_year":kr_year, "kr_comment":kr_comment, "kr_rating":kr_rating}
data_list.append(data)
result_df = pd.DataFrame(data_list, columns=['kr_c_name','pre_code','kr_mov_url','kr_title','kr_year','kr_comment','kr_rating'])
result_df.to_excel(f'C:/RealData/result_data02.xlsx', index=False)
# 예시 -> range를 5로 확정할 경우 5개가 아닌 데이터에서 에러가 남 따라서 해당 모듈의 length로 해결.
- 최종 데이터 프레임
kr_c_name | kr_mov_url | movie_id | kr_title | kr_year | kr_comment | kr_rating |
박평식 | /movie/info/?movie_id=55371 | 55371 | 캔 유 킵 어 시크릿? | 2019 | 푼수 옆에 철부지 | 3 |
박평식 | /movie/info/?movie_id=7201 | 7201 | 타이페이 스토리 | 1985 | 시대의 톱니에 낀 떠돌이들의 권태와 불안 | 7 |
박평식 | /movie/info/?movie_id=55331 | 55331 | 왓 데이 해드 | 2018 | 가까운 타인, 동지애가 필요한 시간 | 6 |
박평식 | /movie/info/?movie_id=53448 | 53448 | 신의 한 수: 귀수편 | 2019 | 만취한 선무당이 칼부림하듯 | 3 |
박평식 | /movie/info/?movie_id=55389 | 55389 | 우먼 인 할리우드 | 2018 | 대장은 지나 데이비스 | 6 |
박평식 | /movie/info/?movie_id=55396 | 55396 | 하이 라이프 | 2018 | 기괴한 불임클리닉, 옹색한 육아일기 | 6 |
박평식 | /movie/info/?movie_id=54815 | 54815 | 터미네이터: 다크 페이트 | 2019 | 반갑되 아쉬운 사라 코너 | 6 |
박평식 | /movie/info/?movie_id=54608 | 54608 | 날씨의 아이 | 2019 | 황홀하게 뜬구름 잡기 | 5 |
˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ | ˙˙˙˙ |
'Programming > Python' 카테고리의 다른 글
[파이썬] 웹 url 호출하기 requests post/get (1) | 2021.06.09 |
---|---|
[Python] 정규표현식 텍스트 전처리 (원하는 문자 추출) (0) | 2021.06.05 |
[Python] 파이썬 이미지 사이즈 분류하기 (0) | 2021.06.02 |
[Python] 파이썬 영화 사이트 (씨네21) 크롤링 (1) | 2021.05.31 |
파이썬 판다스 하나의 행을 여러 행으로 나누기 (0) | 2021.05.12 |
댓글