Python Selenium파이썬으로 네이버 블로그 크롤링, 뷰탭 순위 확인하는 스크립트 (python, selenium)

블로그 글: Selenium으로 네이버 View 탭 순위 확인 자동화 (초보자 가이드)

안녕하세요! 오늘은 Python과 Selenium을 이용해서 네이버 View 탭에서 내 블로그 글이 특정 키워드로 몇 위에 노출되는지 확인하는 방법을 알아보겠습니다. 블로그를 운영하다 보면 내 글의 순위가 궁금할 때가 많은데, 매번 직접 검색하기는 번거롭죠. 이 코드를 활용하면 순위 확인을 자동화할 수 있습니다. Selenium 초보자분들도 쉽게 따라 하실 수 있도록 차근차근 설명해 드릴게요!


(영상 내용 요약)

영상에서는 whereispost.com 같은 기존 순위 확인 사이트가 블로그 탭 기준이라 View 탭 전체 순위와 다를 수 있다는 점을 지적하며, Selenium으로 View 탭의 실제 노출 순위를 정확히 파악하는 코드를 작성합니다. 처음에는 단일 키워드/URL로 시작해서, 여러 키워드와 URL을 처리하고, 스크롤을 통해 더 많은 순위를 확인하는 로직까지 구현합니다.


왜 직접 만들까요?

기존 순위 확인 사이트도 편리하지만, 몇 가지 아쉬운 점이 있습니다.

  1. 정확성: 영상에서 언급된 것처럼, '블로그' 필터링 기준 순위와 'View' 탭 전체 순위는 다를 수 있습니다. 우리는 사용자들이 실제로 보게 되는 View 탭 기준의 정확한 순위를 알고 싶습니다.
  2. 커스터마이징: 내 블로그뿐만 아니라 경쟁 블로그의 순위 변화를 추적하거나, 특정 순위 이하로 떨어졌을 때 알림을 받는 등 원하는 기능을 추가하기 어렵습니다.
  3. 학습: 직접 코드를 작성하며 웹 크롤링과 자동화 원리를 배우는 좋은 기회가 됩니다.

준비물

  1. Python: 설치되어 있지 않다면 python.org에서 설치해주세요.
  2. pip: Python 패키지 설치 도구 (Python 설치 시 보통 함께 설치됩니다.)
  3. Selenium: 웹 브라우저 자동화 라이브러리
  4. webdriver-manager: 웹 드라이버(ChromeDriver 등)를 쉽게 관리하는 라이브러리
  5. 웹 브라우저: Chrome (예제 기준)
  6. 코드 편집기: VS Code, PyCharm 등 편한 것을 사용하세요.

Step 1: 라이브러리 설치 및 기본 설정

먼저 필요한 라이브러리를 설치합니다. 터미널(명령 프롬프트)을 열고 다음 명령어를 입력하세요.

pip install selenium webdriver-manager

이제 코드를 작성할 Python 파일(app.py 등으로 이름 지정)을 만들고, 기본적인 Selenium 설정을 해줍니다.

# app.py
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException # 오류 처리용
from webdriver_manager.chrome import ChromeDriverManager

# Chrome 드라이버 자동 설치 및 설정
service = Service(ChromeDriverManager().install())
options = Options()
# options.add_argument("--headless")  # 브라우저 창을 띄우지 않으려면 주석 해제
# options.add_argument("--log-level=3") # 불필요한 로그 숨기기
# options.add_experimental_option('excludeSwitches', ['enable-logging']) # 불필요한 로그 숨기기

# WebDriver 실행
driver = webdriver.Chrome(service=service, options=options)
print("WebDriver 초기화 완료")
  • webdriver-manager가 알아서 ChromeDriver를 다운로드하고 경로를 설정해줍니다.
  • options를 사용하면 브라우저 창 숨김 등의 설정을 할 수 있습니다.

Step 2: 검색할 키워드 및 타겟 블로그 URL 정의

이제 어떤 키워드로 검색해서 어떤 블로그 글의 순위를 찾을지 정해야 합니다.

# 검색할 키워드 (영상에서는 'python flask')
search_query = "python flask"
# 순위를 찾고 싶은 내 블로그 글의 전체 URL (영상 예시)
target_blog_link = "https://blog.naver.com/nkj2001/222787366282" # 예시 URL입니다. 실제 URL로 변경하세요.

Step 3: 네이버 View 탭 검색 URL 만들고 접속하기

키워드를 이용해서 네이버 View 탭 검색 결과 페이지 URL을 만듭니다. 네이버 View 탭 검색 URL은 보통 아래와 같은 형식을 가집니다.

https://search.naver.com/search.naver?where=view&sm=tab_jum&query=[검색어]

Python의 f-string을 사용하면 쉽게 URL을 조합할 수 있습니다.

# 검색 URL 생성 (f-string 활용)
search_link = f"https://search.naver.com/search.naver?where=view&sm=tab_jum&query={search_query}"

print(f"검색 URL: {search_link}")

# 생성된 URL로 이동
driver.get(search_link)

# 페이지 로딩 대기 (네트워크 상태에 따라 조절)
time.sleep(2)
print(f"'{search_query}' 검색 결과 페이지 로딩 완료")
  • driver.get(url): 해당 URL로 브라우저를 이동시킵니다.
  • time.sleep(초): 페이지가 완전히 로딩될 시간을 벌어줍니다.

Step 4: 타겟 블로그 글 찾기 (기본)

View 탭 검색 결과 페이지에서 우리가 찾는 블로그 글(정확히는 해당 글로 연결되는 링크 <a> 태그)을 찾아야 합니다. 가장 확실한 방법은 href 속성값(즉, URL)이 일치하는 링크를 찾는 것입니다.

# 예외 처리 구문 시작 (try...except)
# 타겟 블로그 링크를 못 찾을 경우를 대비
try:
    # 링크 URL(href)을 기준으로 타겟 엘리먼트 찾기
    # CSS 선택자: a 태그 중 href 속성값이 target_blog_link와 일치하는 것
    # 주의: 작은따옴표(')와 큰따옴표(") 사용에 유의하세요.
    link_selector = f'a[href^="{target_blog_link}"]' # href가 타겟 링크로 시작하는 a 태그
    element = driver.find_element(By.CSS_SELECTOR, link_selector)
    print("타겟 블로그 링크 엘리먼트 찾음!")

    # --- (다음 단계: 순위 찾기 로직이 여기에 들어감) ---

except NoSuchElementException:
    # 엘리먼트를 찾지 못했을 때 실행될 코드
    print("오류: 페이지 내에서 타겟 블로그 링크를 찾을 수 없습니다.")
    # --- (다음 단계: 스크롤 로직이 여기에 들어감) ---

# input("확인 후 Enter를 누르면 종료됩니다...") # 중간 확인용
driver.quit() # WebDriver 종료
  • find_element(By.CSS_SELECTOR, 선택자): CSS 선택자를 이용해 웹페이지에서 특정 HTML 요소를 찾습니다.
  • a[href^="..."]: <a> 태그 중에서 href 속성값이 특정 문자열(target_blog_link)로 시작하는 요소를 찾습니다. ^=는 '시작하는'을 의미합니다. (Naver 링크 뒤에 추가 파라미터가 붙는 경우가 있어 ^=를 사용합니다.)
  • try...except NoSuchElementException: find_element는 요소를 찾지 못하면 NoSuchElementException 오류를 발생시키고 프로그램이 종료됩니다. 이를 방지하기 위해 try...except 구문으로 감싸 오류 발생 시 대처할 코드를 작성합니다.

Step 5: 타겟 블로그 순위 찾기

링크(<a>)를 찾았다면, 이제 그 링크가 포함된 리스트 아이템(<li>)으로 거슬러 올라가 순위 정보를 가져와야 합니다. 순위 정보는 보통 data-cr-rank라는 속성에 저장되어 있습니다.

부모 요소를 찾아 올라가는 방법은 여러 가지가 있지만, 여기서는 XPath의 ..를 사용합니다. ..는 현재 요소의 바로 위 부모 요소를 의미합니다.

# Step 4의 try 블록 안에 추가합니다.
# --- (element = driver.find_element... 다음 줄부터) ---

current_rank = -1 # 순위를 찾지 못했을 경우 기본값
blog_found = False # 블로그를 찾았는지 여부 플래그

# 부모 요소를 거슬러 올라가며 순위(data-cr-rank) 속성을 찾음
while True: # 특정 조건을 만족할 때까지 무한 반복 (break로 탈출)
    try:
        # 현재 element의 'data-cr-rank' 속성값 가져오기 시도
        rank_text = element.get_attribute("data-cr-rank")

        if rank_text is not None: # 순위 속성값이 있다면
            current_rank = int(rank_text) # 정수로 변환
            print(f"현재 랭크 찾음: {current_rank}")
            blog_found = True # 찾았음 플래그 설정
            break # 순위를 찾았으므로 while 루프 탈출
        else: # 순위 속성값이 없다면 (아직 원하는 부모가 아님)
            print("현재 랭크 못찾음 (부모 요소로 이동)")
            # 부모 요소로 이동 (XPath 사용: './..'는 현재 요소의 부모)
            element = element.find_element(By.XPATH, "./..")

    except NoSuchElementException: # 더 이상 부모 요소가 없으면 오류 발생
        print("오류: 순위 정보를 포함한 부모 요소를 찾지 못하고 최상위까지 도달함.")
        break # while 루프 탈출

# 최종 결과 출력 (try...except 블록 바깥, driver.quit() 이전)
if blog_found:
    print(f"최종 결과 >> 키워드 '{search_query}' / 순위: {current_rank}등")
else:
    print(f"최종 결과 >> 키워드 '{search_query}' / 순위를 찾지 못했습니다.")

# input("확인 후 Enter를 누르면 종료됩니다...")
# driver.quit()
  • while True:: 순위 정보를 찾거나 더 이상 올라갈 부모가 없을 때까지 계속 부모 요소를 탐색합니다.
  • element.get_attribute("속성이름"): 해당 요소의 특정 속성값을 가져옵니다. 값이 없으면 None을 반환합니다.
  • element.find_element(By.XPATH, "./.."): 현재 element의 부모 요소를 찾아 다시 element 변수에 할당합니다. 이 과정을 반복하며 위로 올라갑니다.
  • blog_found 플래그: 순위를 성공적으로 찾았는지 기록하여 최종 결과 출력 시 사용합니다.

Step 6: 타겟 블로그가 30위 내에 없을 때 (스크롤 처리)

처음 페이지에는 보통 30개 정도의 글만 보입니다. 내 글이 그 아래 있다면 스크롤을 내려서 추가 결과를 로딩해야 합니다. Selenium은 JavaScript 코드를 실행할 수 있는데, 이를 이용해 스크롤을 내릴 수 있습니다.

# Step 4의 except NoSuchElementException 블록 안에 추가합니다.
# --- (print("오류: 페이지 내에서...") 다음 줄부터) ---

print("-> 스크롤을 실행합니다.")
# JavaScript 실행: window.scrollBy(가로, 세로) - 페이지 끝까지 스크롤
driver.execute_script("window.scrollBy(0, 10000);")
# 스크롤 후 새 글 로딩 대기
time.sleep(3)

# --- (스크롤 후 다시 찾는 로직 추가 필요) ---
  • driver.execute_script("자바스크립트 코드"): 브라우저에서 JavaScript 명령을 실행합니다.
  • window.scrollBy(0, 10000): 페이지를 세로 방향으로 10000픽셀만큼 아래로 스크롤합니다. (페이지 맨 아래까지 내리는 효과)

하지만 이 상태로는 스크롤만 하고 끝나버립니다. 스크롤 후에도 타겟 블로그를 다시 찾아야 하고, 그래도 없으면 또 스크롤하는 과정을 반복해야 합니다. for 루프를 사용해 이 과정을 제한된 횟수만큼 반복하도록 수정해 봅시다.

# Step 4의 try...except 구문을 포함한 전체 로직 수정

max_scroll_attempts = 7 # 최대 스크롤 시도 횟수
blog_found = False
current_rank = -1

# Step 4의 link_selector 정의는 그대로 둡니다.
# link_selector = f'a[href^="{target_blog_link}"]'

for attempt in range(max_scroll_attempts):
    try:
        # 타겟 블로그 링크 엘리먼트 찾기
        element = driver.find_element(By.CSS_SELECTOR, link_selector)
        print(f"시도 {attempt+1}: 타겟 블로그 링크 엘리먼트 찾음!")

        # --- Step 5: 순위 찾기 로직 (while True 부분) ---
        while True:
            try:
                rank_text = element.get_attribute("data-cr-rank")
                if rank_text is not None:
                    current_rank = int(rank_text)
                    print(f"현재 랭크 찾음: {current_rank}")
                    blog_found = True
                    break # while 탈출
                else:
                    print("현재 랭크 못찾음 (부모 요소로 이동)")
                    element = element.find_element(By.XPATH, "./..")
            except NoSuchElementException:
                print("오류: 순위 정보를 포함한 부모 요소를 찾지 못함.")
                break # while 탈출
        # --- 순위 찾기 로직 끝 ---

        if blog_found: # 순위를 찾았다면
            break # for 루프 탈출

    except NoSuchElementException:
        # 엘리먼트를 찾지 못했을 때 (현재 화면에 없음)
        print(f"시도 {attempt+1}: 타겟 블로그 못 찾음 -> 스크롤합니다.")
        driver.execute_script("window.scrollBy(0, 10000);")
        time.sleep(3) # 로딩 대기

# 최종 결과 출력 (for 루프 바깥, driver.quit() 이전)
if blog_found:
    print(f"최종 결과 >> 키워드 '{search_query}' / 순위: {current_rank}등")
else:
    print(f"최종 결과 >> 키워드 '{search_query}' / {max_scroll_attempts}번 스크롤 했지만 순위를 찾지 못했습니다.")

# input("확인 후 Enter를 누르면 종료됩니다...")
# driver.quit()
  • for attempt in range(max_scroll_attempts):: 최대 7번까지 스크롤과 검색을 반복합니다.
  • if blog_found: break: try 블록 내에서 순위를 성공적으로 찾으면 더 이상 스크롤할 필요가 없으므로 for 루프를 탈출합니다.
  • except 블록에서는 스크롤만 하고 다음 for 반복으로 넘어갑니다.

Step 7: N개의 키워드, N개의 타겟 블로그로 로직 적용하기

이제 여러 개의 키워드와 해당 키워드에 맞는 타겟 블로그 URL 쌍을 처리하도록 코드를 확장해 봅시다. 리스트와 zip 함수를 사용하면 됩니다.

# Step 2 수정
# 검색할 키워드 리스트
search_queries = ["python flask", "python selenium"]
# 순위를 찾고 싶은 타겟 블로그 URL 리스트 (키워드와 순서 맞춰야 함)
target_blog_links = [
    "https://blog.naver.com/isaac7263/222074412179", # python flask 예시
    "https://blog.naver.com/lread90/..." # python selenium 타겟 URL (실제 URL로 변경)
]

# Step 3 ~ Step 6 로직을 for문으로 감싸기

# WebDriver 초기화는 맨 위에 한 번만
# driver = webdriver.Chrome(service=service, options=options)

results = [] # 결과를 저장할 리스트

# zip으로 키워드와 타겟 링크를 묶어서 반복
for search_query, target_blog_link in zip(search_queries, target_blog_links):
    print(f"\n--- 키워드: '{search_query}' / 타겟 URL: {target_blog_link} 순위 확인 시작 ---")
    search_link = f"https://search.naver.com/search.naver?where=view&sm=tab_jum&query={search_query}"
    driver.get(search_link)
    time.sleep(2)

    max_scroll_attempts = 7
    blog_found = False
    current_rank = -1
    link_selector = f'a[href^="{target_blog_link}"]'

    for attempt in range(max_scroll_attempts):
        try:
            element = driver.find_element(By.CSS_SELECTOR, link_selector)
            print(f"시도 {attempt+1}: 타겟 블로그 링크 엘리먼트 찾음!")

            while True:
                try:
                    rank_text = element.get_attribute("data-cr-rank")
                    if rank_text is not None:
                        current_rank = int(rank_text)
                        print(f"현재 랭크 찾음: {current_rank}")
                        blog_found = True
                        break
                    else:
                        print("현재 랭크 못찾음 (부모 요소로 이동)")
                        element = element.find_element(By.XPATH, "./..")
                except NoSuchElementException:
                    print("오류: 순위 정보를 포함한 부모 요소를 찾지 못함.")
                    break

            if blog_found:
                break

        except NoSuchElementException:
            print(f"시도 {attempt+1}: 타겟 블로그 못 찾음 -> 스크롤합니다.")
            driver.execute_script("window.scrollBy(0, 10000);")
            time.sleep(3)

    # 각 키워드별 결과 저장
    result_text = ""
    if blog_found:
        result_text = f"키워드 '{search_query}' / 순위: {current_rank}등"
        print(f"결과 >> {result_text}")
    else:
        result_text = f"키워드 '{search_query}' / 순위 찾지 못함 (순위권 밖 또는 URL 오류)"
        print(f"결과 >> {result_text}")
    results.append(result_text) # 결과를 리스트에 추가

print("\n--- 모든 작업 완료 ---")
for res in results:
    print(res)

driver.quit()
  • search_queries, target_blog_links: 키워드와 URL을 리스트로 관리합니다. 순서가 중요합니다! 첫 번째 키워드에는 첫 번째 URL이 대응되어야 합니다.
  • zip(list1, list2): 두 리스트의 요소들을 순서대로 짝지어 튜플로 만들어줍니다. for 문과 함께 사용하면 각 반복마다 해당 순서의 키워드와 URL을 가져올 수 있습니다.
  • 기존 로직 전체를 for search_query, target_blog_link in zip(...) 루프 안으로 넣습니다.
  • results 리스트: 각 키워드별 순위 확인 결과를 저장하여 마지막에 한 번에 출력합니다.

Step 8: 프로그램 추가 아이디어 (영상 내용)

영상에서는 이 기본 로직을 더 발전시킬 수 있는 아이디어를 제시합니다.

  • 엑셀 저장: openpyxl이나 pandas 라이브러리를 사용하여 키워드, URL, 확인된 순위, 확인 시간 등을 엑셀 파일로 깔끔하게 정리하고 기록할 수 있습니다.
  • GUI 입히기: Tkinter, PyQt 등의 라이브러리를 사용하여 사용자가 키워드와 URL을 쉽게 입력하고 버튼 클릭으로 순위를 확인할 수 있는 그래픽 사용자 인터페이스(GUI) 프로그램을 만들 수 있습니다. (다만, GUI 개발은 코드량이 상당히 늘어납니다.)

마무리

오늘은 Selenium을 이용해 네이버 View 탭에서 블로그 글의 순위를 확인하는 기본적인 방법을 알아봤습니다. 여기서 더 나아가 스크롤 처리, 여러 키워드 처리까지 구현해 보았습니다. 이 코드를 바탕으로 여러분의 필요에 맞게 기능을 추가하고 개선해 보세요! 꾸준히 순위를 추적하고 싶다면 엑셀 저장 기능을, 더 편리하게 사용하고 싶다면 GUI 기능을 추가하는 것을 추천합니다.

궁금한 점이 있다면 언제든지 댓글로 남겨주세요! 감사합니다.

0

상호: 위듀오 | 대표 : 김영빈 | 전화번호 : 010-2659-1352

이메일:help@weduo.gg

사업자등록번호 : 508-11-51881 | 통신판매신고번호 : // 

주소 : 경남 양산시 동면 금산 2길 12


호스팅제공자:(주)아임웹

Copyright. 히든 마케팅. All rights reserved.

..

모든 문의는 admin@월천무기.com 으로 연락주세요