네이버 블로그 크롤링

SeungHyun·2023년 12월 24일
1

WebCrawling

목록 보기
2/3


0. 개요

  • 네이버 특정 검색어와 검색기간을 설정하여 네이버 뷰(view) 검색 후 출력되는 블로그의 url을 수집하고 url을 하나씩 순회하면서 블로그의 제목, 글작성 날짜, 글 내용들을 크롤링한다.
  • 검색 api신청이 어렵지 않으나 컴퓨터를 모르는 이들도 쉽게 사용할 수 있도록 검색 api는 활용하지 않았다.

Date비고
'23. 12. 25.최초 작성


1. 사전 준비

1-A. pip install

selenium==4.16.0
bs4==0.0.1
requests==2.31.0
pandas==2.1.4
konlpy==0.6.0
matplotlib==3.8.2
seaborn==0.13.0

1-B. chrome driver

■ 링크 참고



2. 전체 코드

■ 나의 git
아래 코드 해석과 전체 코드가 상이할 수 있음.



3. 코드 해석


3-A. pip

from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from datetime import datetime
import requests
import pandas as pd
import konlpy
import matplotlib.pyplot as plt
import seaborn as sns
import time
import os

3-B. 코드 내 사용할 함수 선언

#################### 함수 선언
def infinite_loop(browser, sleepDelay):
    # 최초 페이지 스크롤 설정
    # 스크롤 시키지 않았을 때의 전체 높이
    last_page_height = browser.execute_script("return document.documentElement.scrollHeight")

    while True:
        # 윈도우 창을 0에서 위에서 설정한 전체 높이로 이동
        browser.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);")
        time.sleep(sleepDelay)
        # 스크롤 다운한 만큼의 높이를 신규 높이로 설정 
        new_page_height = browser.execute_script("return document.documentElement.scrollHeight")
        # 직전 페이지 높이와 신규 페이지 높이 비교
        if new_page_height == last_page_height:
            time.sleep(sleepDelay)
            # 신규 페이지 높이가 이전과 동일하면, while문 break
            if new_page_height == browser.execute_script("return document.documentElement.scrollHeight"):
                break
        else:
            last_page_height = new_page_height

def log_check(f, str):
    now = datetime.now()
    f_str = f"{now}    {str}"
    f.write(f_str + "\n")
    print(f_str)
  • infinite_loop: selenium으로 네이버 검색 후 최하단까지 스크롤을 내리는 함수.
  • log_check: 진행 상황을 log.txt 파일로 생성하는 함수.

3-C. 기타 파라미터 선언

#################### 1. 검색단어, 검색기간 및 기타 파라미터 설정
current_path = os.getcwd()

search_word = "꿀_"
start_date = "20231101" #yyyymmdd 형식
end_date  = "20231130" #yyyymmdd 형식

# 출처: 블로그
# 정렬: 관련도순
target_url = f"https://search.naver.com/search.naver?query={search_word}&nso=p%3Afrom{start_date}to{end_date}&where=blog&sm=tab_opt"


sleepDelay = 1.5



frist_url_list = [] # 1차로 검색 후 모든 blog에 대해 url을 수집함.


df_text = pd.DataFrame(columns=['date', 'url', 'title', 'text']) 
df_idx = 0
# date: 네이버 블로그 글 생성 날짜
# url: 스크래핑한 url
# title: 스크래핑한 url 내 블로그 제목
# text: 스크래핑한 url 내 블로그 내용


today = f"{datetime.now().year}{datetime.now().month}{datetime.now().day}"
# log파일
f = open(f'{current_path}\\crawler_log_{today}.txt', 'w')
f.write(f"[크롤링 파라미터]" + '\n')
f.write(f"검색 단어: {search_word}" + '\n')
f.write(f"검색 시작일: {start_date}" + '\n')
f.write(f"검색 종료일: {end_date}" + '\n')
f.write("================================================" + '\n')

3-D. 검색 단어 및 기간을 기준으로 네이버 검색 진행 후 url 수집

#################### 2. 검색단어, 검색기간을 기준으로 검색 진행 ~ # 3. 검색에 나온 blog url 수집
log_check(f, "크롤링 시작")
browser = webdriver.Chrome()
browser.get(target_url)
browser.implicitly_wait(sleepDelay * 5)

log_check(f, "검색결과 최하단 이동")
infinite_loop(browser, sleepDelay)


log_check(f, "url수집 시작")
url_table = browser.find_elements(By.CLASS_NAME, 'bx')
for i in range(1, len(url_table)):
    if i % 1000 == 0: log_check(f, f"{i}개의 url 수집. 계속해서 수집 진행중")
    try:
        url = browser.find_elements(By.CSS_SELECTOR, f'#sp_blog_{str(i)}')[-1].find_element(By.CLASS_NAME, 'title_link').get_attribute('href')
        frist_url_list.append(url)
    except:
        break

log_check(f, f"url수집 완료. 전체 {len(frist_url_list)}개의 url")
df_ful = pd.DataFrame({'url' : frist_url_list})
df_ful.to_csv(f'{current_path}\\url_list_{today}.csv', index = False, encoding='utf-8-sig') # 크롤링한 url_list
log_check(f, "url csv 생성 완료")
browser.quit()
  • 중간 중간 log.txt 파일 업데이트 및 Dataframe, csv 파일 생성

3-E. 수집한 url 순회하며 blog 내 데이터 크롤링

#################### 4. 수집한 blog url을 순회하면서 글생성시간(date), 제목(title), 내용(text)를 수집하여 DataFrame에 저장
log_check(f, "수집한 url 경로에 따라 크롤링 시작")
for idx, url in enumerate(frist_url_list):
    m_url = "https://m." + url.replace("https://","") # //blog.naver 의 경우 크롤링을 막아놔서 모바일 경로인 m.으로 우회
    res = requests.get(m_url)
    res.raise_for_status()
    soup = BeautifulSoup(res.text, "lxml")

    try:
        date = soup.find("p", attrs={'class':'blog_date'}).text.rstrip()
        title = soup.find("span", attrs={'class':'se-fs- se-ff-'}).text
        text = soup.find("div", attrs={'class':'se-main-container'}).text

        df_text.loc[df_idx] = [date, url, title, text]
        df_idx += 1
    except:
        continue

    if (idx + 1) % 1000 == 0: log_check(f, f"{idx + 1}개 url 크롤링 완료. 계속해서 크롤링 진행중")

log_check(f, f"url 크롤링 완료")
log_check(f, f"네이버 블로그 크롤링 완전 종료.")
f.close()

이후 코드는 크롤러와 관련 없는 부분이기에 포함하지 않았다.

profile
어디로 가야하오

0개의 댓글