# step1.프로젝트에 필요한 패키지 불러오기
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import pandas as pd
import requests
import re
import numpy as np
from selenium.webdriver.common.keys import Keys
2. 크롬드라이버 설정 및 로그인 정보전달
header = {'User-Agent': ''}
d = webdriver.Chrome('C:/Users/XXXXXXXXX/Downloads/chromedriver.exe') # webdriver = chrome
shoppingmall_review="/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[2]/div/div[2]/ul/li[4]/a/strong"#함수 선언
def add_dataframe(dit,reviews,stars,cnt): #데이터 프레임에 저장#데이터 프레임생성
df1=pd.DataFrame(columns=['크롤링구분','리뷰','평점'])
n=1
if (cnt>0):
for i in range(0,cnt-1):
df1.loc[n]=[dit[i],reviews[i],stars[i]] #해당 행에 저장
i+=1
n+=1
else:
df1.loc[n]=['null','null','null']
n+=1
return df1
3. 크롤링 대상 물품을 선정하고 URL로 정리 후 크롤링진행[Main]
**df2에 해당하는 데이터
- 실제 수집URL을 회사별로 관리하고 아래 for문에서 해당 df2를 순회하며 크롤링진행
- 파일로 담아놓아도 되고 DB Table형태로 관리해도 됨(개인적으로 Table형태를 선호함)
df1 = pd.DataFrame(columns=['크롤링구분','평점','리뷰'])
df4 = pd.DataFrame(columns=['크롤링구분','평점','리뷰'])
for dit,ns_address in zip(df2['크롤링구분'],df2['수집URL']):
#print(name_, category_ ,ns_address, "\n")
d.implicitly_wait(3)
d.get(ns_address)
req = requests.get(ns_address,verify=False)
html = req.text
soup = BeautifulSoup(html, "html.parser")
sleep(2)
element=d.find_element_by_xpath(shoppingmall_review)
d.execute_script("arguments[0].click();", element)
sleep(2)
# 리뷰 가져오기
reviews=[]
stars=[]
total_list=[]
cnt=1 #리뷰index
page=1
while True:
j=1
sleep(2)
while True: #한페이지에 20개의 리뷰, 마지막 리뷰에서 error발생
try:
star=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/ul/li[1]/div[1]/span[1]').text
star = star.replace("평점","")
review=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/ul/li['+str(j)+']/div[2]/div[1]/p').text
#reviews.append(review)
total_list.append((dit,star,review))
if j%2==0: #화면에 2개씩 보이도록 스크롤
ELEMENT = d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/ul/li['+str(j)+']/div[2]/div[1]/p')
d.execute_script("arguments[0].scrollIntoView(true);", ELEMENT)
j+=1
cnt+=1
except:
break
sleep(2)
if page<11:#page10까지 적용
try: #리뷰의 마지막 페이지에서 error발생
page +=1
next_page=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/div[3]/a['+str(page)+']').click()
except:
breakelse :
try: #page11부터
page+=1
if page%10==0:
next_page=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/div[3]/a[11]').click()
elif page%10==1:
next_page=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/div[3]/a[12]').click()
else :
next_page=d.find_element_by_xpath('/html/body/div/div/div[2]/div[2]/div[2]/div[3]/div[6]/div[3]/a['+str(page%10+1)+']').click()
except:
break
df4 = pd.DataFrame(total_list, columns=['크롤링구분','평점','리뷰'])
#df4=add_dataframe(dit,reviews,stars,cnt)
# step1.프로젝트에 필요한 패키지 불러오기
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import pandas as pd
import requests
import re
import numpy as np
from selenium.webdriver.common.keys import Keys
# step2.로그인 정보 및 검색할 회사 미리 정의, 해당 회사의 리뷰 끝 페이지도 정의
usr = ""pwd = ""
- 실제 수집URL을 회사별로 관리하고 아래 for문에서 해당 df2를 순회하며 크롤링진행
- 파일로 담아놓아도 되고 DB Table형태로 관리해도 됨(개인적으로 Table형태를 선호함)
for name,dit,ns_address,page in zip(df2['이름'],df2['크롤링구분'],df2['수집URL'],df2['설명']):
page = int(page)
# step5.원하는 회사의 리뷰 페이지까지 이동
header = {'User-Agent': ''}
driver.implicitly_wait(3)
driver.get(ns_address)
req = requests.get(ns_address,verify=False)
html = req.text
soup = BeautifulSoup(html, "html.parser")
if k ==0:
driver.find_element_by_css_selector("button.btn_close_x_ty1 ").click()
time.sleep(3)
# step6.원하는 회사의 직무/근속여부/일시/요약/평점/장점/단점/경영진에게 바라는 점 크롤링 (for문으로 반복)for i in range(page):
try:
user_info = driver.find_elements_by_css_selector("span.txt1")
count = int(len(user_info)/4)
list_user_info = []
#별점
stars = driver.find_elements_by_css_selector("div.star_score")
for j in stars:
a = j.get_attribute('style')
if a[7:9] == '20':
list_stars.append("1")
elif a[7:9] == '40':
list_stars.append("2")
elif a[7:9] == '60':
list_stars.append("3")
elif a[7:9] == '80':
list_stars.append("4")
else:
list_stars.append("5")
#요약 정보
summery = driver.find_elements_by_css_selector("h2.us_label")
for j in summery:
list_summery.append(j.text)
#장점, 단점, 경영진에게 바라는 점
list_review = []
review = driver.find_elements_by_css_selector("dd.df1")
for j in review:
list_review.append(j.text)
for j in range(count): #한 페이지에 정보 5set씩 나옴. 마지막 페이지는 5개 미만일 수 있으므로 count 변수를 반복횟수로 넣어줌.
a = list_review[3*j]
list_stars.append("5")
list_summery.append(a)
#list_merit.append(a)
b = list_review[3*j+1]
list_stars.append("1")
list_summery.append(b)
#list_disadvantages.append(b)
except:
# 다음 페이지 클릭 후 for문 진행, 끝 페이지에서 다음 페이지 클릭 안되는 것 대비해서 예외처리 구문 추가
try:
driver.find_element_by_css_selector("a.btn_pgnext").click()
time.sleep(15)
except:
print("break1")
break# 다음 페이지 클릭 후 for문 진행, 끝 페이지에서 다음 페이지 클릭 안되는 것 대비해서 예외처리 구문 추가
try:
driver.find_element_by_css_selector("a.btn_pgnext").click()
time.sleep(15)
except:
breakprint("break2")
print(name, i)
k=k+1
# step7.pandas 라이브러리로 표 만들기
total_data = pd.DataFrame()
total_data['크롤링구분'] = '잡플래닛'
total_data['평점'] = pd.Series(list_stars)
total_data['리뷰'] = pd.Series(list_summery)
import requests
from selenium import webdriver
import time
from bs4 import BeautifulSoup
import pandas as pd
import random
import urllib.parse as parse
from sqlalchemy import create_engine
import pymysql
from selenium.webdriver.common.keys import Keys
2. 반복문으로 1000페이지까지 크롤링진행
results = []
for i in range(1, 1001):
url = 'https://movie.naver.com/movie/point/af/list.nhn?&page={}'.format(i)
r = requests.get(url)
bs = BeautifulSoup(r.text, "lxml")
trs = bs.select("table.list_netizen > tbody > tr")
for tr in trs: #다수의 평점
number = tr.select_one("td.ac.num").text
writer = tr.select_one("td.num > a.author").text
tr_data = tr.select_one("td.title")
title = tr_data.select_one("a").text
point = tr_data.select_one("div.list_netizen_score > em").text
if point =='1' or point =='2':
point = '1'elif point =='3' or point =='4':
point = '2'elif point =='5' or point =='6':
point = '3'elif point =='7' or point =='8':
point = '4'else:
point = '5'# td class="title" 태그에서 a, div, br 태그 제거# extract() 함수는 태그와 태그의 내용까지 모두 제거
[x.extract() for x in tr_data.select("a")]
[x.extract() for x in tr_data.select("div")]
[x.extract() for x in tr_data.select("br")]
content = tr_data.text.strip()
#리뷰가 없으면 건너뛰자if content ==None:
continue
results.append(('네이버영화',point,content))
- OpenDart에서 Key로 사용하는 기업코드(corp_code)를 받아와서 Data Frame으로 저장
- 추후 해당 기업코드로 다양한 OpenDart API 활용
기본적인 라이브러리 들을 Import합니다
import pandas as pd
import requests
import xml.etree.ElementTree as et
from io import BytesIO
from zipfile import ZipFile
import urllib3
해당 구조로 하는 이유는 다른 API 접속 프로그램을 만들때 url_json과 params 부분만 수정 및 추가해주면 되기 때문입니다.
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) #워닝 메시지 미출력#[1] 고유번호조회### OPENDART 개발 가이드
url_json = 'https://opendart.fss.or.kr/api/corpCode.xml'
api_key = '발급받은APIKey'
params = {
'crtfc_key': api_key,
}
Zipfile형태는 file로 로드한 뒤에 읽어내야 합니다.
아래처럼 requests로 불러온뒤 XML을 다운받은 후 string으로 읽습니다.
# OpenDART에서 Zipfile 받아와 객체에 저장하기
u = requests.get(url_json, params=params,verify=False)
zipfile_bytes = u.content
zipfile_obj = ZipFile(BytesIO(zipfile_bytes))
# 압축을 풀어서 XML File을 string으로 담기
xmlfile_objs = {name: zipfile_obj.read(name) for name in zipfile_obj.namelist()}
xml_str = xmlfile_objs['CORPCODE.xml'].decode('utf-8')
읽어서 Dataframe에 담는 부분입니다.
반복문을 사용해 읽어냅니다.
# XML String을 가져와서 DataFrame에 담기
xroot = et.fromstring(xml_str)
df_cols = ["corp_code", "corp_name", "stock_code", "modify_date"]
rows = []
for node in xroot:
res = []
for el in df_cols[0:]:
if node is not None and node.find(el) is not None:
res.append(node.find(el).text)
else:
res.append(None)
rows.append({df_cols[i]: res[i]
for i, _ in enumerate(df_cols)})
df_cor = pd.DataFrame(rows, columns=df_cols)