상세 컨텐츠

본문 제목

[파이썬] 네이버 이웃 블로그 자동 공감 버튼 눌러주기

코딩

by 땡감 2022. 1. 12. 23:37

본문

반응형

네이버에서 블로그를 하는 와이프를 위해 이웃들의 게시글에 좋아요 버튼을 자동으로 눌러주는 프로그램을 만들었다.

나같은 초짜야 아직은 하나를 만들더라도 매번 여러가지 고비가 생기는데 이번에 맞닥뜨린 고비는 참 많았다.

먼저, 크롤링이 아닌척 하기위해 바로 send_keys 함수 대신 pyperclip 패키지를 사용해야 네이버를 속일 수 있었다.

send_keys로 로그인을 하면 캡챠라고 불리는 2단계 로그인을 또 해야한다.

두번째는 selenium과 bs4간 html 객체를 주고 받는 방법이였는데 구글링을 해보니 너무나도 간단해서 허무했다.

html = driver.page_source (단 한줄이다.)

마지막은 시간도 많이 소비하고 해결책을 찾기 어려웠던 부분이였는데 바로 'aria-pressed'라는 특정 속성값을 추출하는 방법이였다.

html상에서는 해당 속성값의 위치도, 해당 값도 잘 보이는데 bs4나 selenium을 사용하면 도무지 추출되지 않았다.

게시글에 이미 좋아요 버튼을 눌렀는지 아닌지를 판별하는 값으로 매우 중요했기에 무조건 방법을 찾아야했다.

몇 시간을 고민하고 구글링하고 코드를 다시 짜봐도 도무지 해결이 안되다가 마지막 자포자기 심정으로 그냥 sleep이나 걸어볼까? 했던것이 결국엔 정답이였다.

html에 대한 지식이 전무하다 보니 aria라는 속성에 대해 전혀 알지 못해서 발생한 문제였다.

해당 값이 동적 반영되므로 반영되는 시간을 기달렸어야 했는데 bs4는 너무나 빨라서 값을 추출하지 못 했고 selenium 역시 내가 sleep을 주지 않았기에 다음 코드를 바로 실행해버려 해당 값을 추출하지 못 했던 거였다.

완성 후, 시연되는 모습을 본 와이프가 신기하다고 하는 모습을 보니 이 맛에 코딩을 하나 싶다.

각설이 길었는데 전체 소스를 공개한다.

크게 바꿀 부분은 자신의 크롬 드라이버위치, 네이버아이디, 네이버패스워드이다.

좀 더 개선해야 부분이 있다면 링크를 따 오기 전에 미리 좋아요 버튼을 눌렀는지를 체크하여 누르지 않은 게시글에 대해서만 링크를 따오는 것인데 좋아요 버튼 체크 유무 태그와 게시글의 링크를 가지고 있는 태그의 위치가 상이하여 더욱 더 연구를 해야할 듯 하다.

 

import time
import pyperclip
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.alert import Alert

driver = webdriver.Chrome('C:/Users/root/PycharmProjects/pythonProject/source/97/chromedriver.exe') #자신의 크롬 드라이버 위치
driver.maximize_window()
site_url = 'https://nid.naver.com/nidlogin.login?svctype=262144&url=http://undefined/aside/'    #네이버 모바일 로그인 URL
driver.get(site_url)

id = ''   #네이버 ID
pw = '' #네이버 패스워드

pyperclip.copy(id)  #id를 클립보드에 복사
driver.find_element(by='name', value='id').send_keys(Keys.CONTROL + 'v')    #id 입력창에 보냄
pyperclip.copy(pw)  #패스워드를 클립보드에 복사
driver.find_element(by='name', value='pw').send_keys(Keys.CONTROL + 'v')    #패스워드를 입력창에 보냄
driver.find_element(by='xpath', value='//*[@id="log.login"]').click()   #로그인 버튼 클릭
time.sleep(0.5)   #로그인 되는 시간을 위해 슬립
driver.find_element(by='xpath', value='//*[@id="HOME_SHORTCUT"]/ul/li[7]/a/div/picture/img').click()    #블로그 아이콘 클릭

#페이지 다운키를 눌러 더 많은 게시글의 링크를 따옴
for i in range(0, 20, 1):   #반복 횟수로 불러올 게시글량 조절 가능
    driver.find_element(by='tag name', value='body').send_keys(Keys.PAGE_DOWN)
    time.sleep(0.5)

html = driver.page_source   #링크를 따와야 하므로 게시글이 많이 불러진 상태에서 html 객체를 생성
soup = BeautifulSoup(html, 'html.parser')
link_list = soup.select('.area_thumb__hWSV2 > a')   #링크 추출
like_cnt = 0    #좋아요 버튼 누른 횟수 저장 변수

#추출된 링크 수 만큼 방문하여 좋아요 버튼 클릭
for i in range(len(link_list)):
    site = (link_list[i]['href'])
    driver.get(site)
    time.sleep(0.5)
    try:
        is_like = driver.find_element(by='xpath', value='//*[@id="body"]/div[10]/div/div[1]/div/div/a').get_attribute('aria-pressed')   #좋아요 버튼 상태 확인
        #print(is_like)
    except Exception:   #간혹 공감 버튼 자체가 없는 게시글이 존재함
        print('공감 버튼 없음')
        continue
    if is_like == 'false':  #좋아요 버튼 상태가 안눌러져있는 상태일 경우에만 좋아요 버튼 클릭
        like_cnt += 1   #좋아요 횟수 1증가
        driver.find_element(by='xpath', value='//*[@id="body"]/div[10]/div/div[1]/div/div/a/span').click()  #하트 클릭
        time.sleep(0.5)
    try:
        time.sleep(1)
        alert = Alert(driver)   #팝업창으로 메시지 뜰 경우를 대비
        alert.accept()
    except Exception:
        continue

print('총 {}개의 게시글 중 {}개의 게시글에 좋아요 버튼을 눌렀습니다.'.format(len(link_list), like_cnt)) 
time.sleep(5)
driver.close()  #열린 창 닫기

 

### 2022년 02월 24일 오후2시 24분 추가 내용 ###

오랜만에 실행해보니 블로그 링크를 따오는 클래스명이 변경되었다.

따라서 클래스명을 수정해서 다시 공유한다.

  • 블로그 링크를 따오는 클래스명 변경 (.area_thumb__hWSV2에서 .thumb_area__IeDdq로 변경)
  • 소스 모듈화

 

import time
import pyperclip
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.alert import Alert
from webdriver_manager.chrome import ChromeDriverManager


id = ''   #네이버 ID
pw = '' #네이버 패스워드
site_url = 'https://nid.naver.com/nidlogin.login?svctype=262144&url=http://undefined/aside/'    #네이버 모바일 로그인 URL

#크롬 실행
def exec_chrom():
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
    driver.maximize_window()
    return driver


#로그인
def login(driver):
    driver.get(site_url)
    pyperclip.copy(id)  # id를 클립보드에 복사
    driver.find_element(by='name', value='id').send_keys(Keys.CONTROL + 'v')  # id 입력창에 보냄
    pyperclip.copy(pw)  # 패스워드를 클립보드에 복사
    driver.find_element(by='name', value='pw').send_keys(Keys.CONTROL + 'v')  # 패스워드를 입력창에 보냄
    driver.find_element(by='xpath', value='//*[@id="log.login"]').click()  # 로그인 버튼 클릭
    time.sleep(0.5)  # 로그인 되는 시간을 위해 슬립
    driver.find_element(by='xpath', value='//*[@id="HOME_SHORTCUT"]/ul/li[7]/a/div/picture/img').click()  # 블로그 아이콘 클릭


#블로그 링크따기
def get_blog(driver):
    for i in range(0, 30, 1):  # 반복 횟수로 불러올 게시글량 조절 가능
        driver.find_element(by='tag name', value='body').send_keys(Keys.PAGE_DOWN)
        time.sleep(0.5)
    html = driver.page_source  # 링크를 따와야 하므로 게시글이 많이 불러진 상태에서 html 객체를 생성
    soup = BeautifulSoup(html, 'html.parser')
    link_list = soup.select('.thumb_area__IeDdQ > a')   #링크 추출
    return link_list


#포스팅별 방문하여 좋아요 클릭
def click_like(driver, link_list):
    like_cnt = 0  # 좋아요 버튼 누른 횟수 저장 변수

    #추출된 링크 수 만큼 방문하여 좋아요 버튼 클릭
    for i in range(len(link_list)):
        site = (link_list[i]['href'])
        driver.get(site)
        time.sleep(0.5)
        try:
            is_like = driver.find_element(by='xpath', value='//*[@id="body"]/div[10]/div/div[1]/div/div/a').get_attribute('aria-pressed')   #좋아요 버튼 상태 확인
            #print(is_like)
        except Exception:   #간혹 공감 버튼 자체가 없는 게시글이 존재함
            print('공감 버튼 없음')
            continue
        if is_like == 'false':  #좋아요 버튼 상태가 안눌러져있는 상태일 경우에만 좋아요 버튼 클릭
            like_cnt += 1   #좋아요 횟수 1증가
            driver.find_element(by='xpath', value='//*[@id="body"]/div[10]/div/div[1]/div/div/a/span').click()  #하트 클릭
            time.sleep(0.5)
        try:
            time.sleep(1)
            alert = Alert(driver)   #팝업창으로 메시지 뜰 경우를 대비
            alert.accept()
        except Exception:
            continue
    return like_cnt


#크롬 닫기
def close(driver, link_list, like_cnt):
    print('총 {}개의 게시글 중 {}개의 게시글에 좋아요 버튼을 눌렀습니다.'.format(len(link_list), like_cnt))
    time.sleep(3)
    driver.close()


#메인
if __name__ == '__main__':
    driver = exec_chrom()
    login(driver)
    link_list = get_blog(driver)
    like_cnt = click_like(driver, link_list)
    close(driver, link_list, like_cnt)

 

반응형

관련글 더보기

댓글 영역