인스타그램 자동화

[파이썬(Python)] 인스타그램 자동 프로그램 만들기 - 자동 댓글 (2)

dev109 2021. 2. 27.
반응형

파이썬 인스타그램 자동화 - 자동 댓글 작성하기

이전 포스팅에서 인스타그램 자동 댓글 작성 기능을 구현했습니다. 그런데 내 프로그램이 이미 댓글 작성한 피드에 중복으로 댓글을 작성한다면? 게시자 입장에서 참 이상한 상황이라고 생각을 할 수도 있고, 프로그램 사용을 의심할수도 있겠죠 ㅠㅠ

이런 문제를 방지하기 위해 댓글 작성전 이미 댓글을 작성했는지 확인하는 기능을 추가하겠습니다.

 

이전 강의 - 인스타그램 자동 좋아요, 자동 댓글

지난번에 작성한 소스코드에 이어서 작성했으니 아래의 링크에서 지난 강의를 참고해주세요.

 

인스타그램 자동 좋아요 1편

 

인스타그램 자동 좋아요 프로그램 만들기 - 파이썬(python), 셀레니움(selenium) - 로그인, 원하는 횟

구현 기능 - 인스타그램 로그인, 설정한 횟수만큼 자동 좋아요 작업 작업환경 - 윈도우10, VS Code, Python3 오늘 구현해 볼 기능은 아주 간단한 인스타그램 로그인과 설정한 횟수만큼 자동으로 좋아

private.tistory.com

인스타그램 자동 좋아요 2편

 

인스타그램 자동 좋아요 프로그램 만들기 - 파이썬(python), 셀레니움(selenium) - 기능 강화 및 예외

구현 기능 - 인스타그램 자동 좋아요 기능 강화 작업환경 - 윈도우10, VS Code, Python3 이번 포스트에서는 이전에 구현했던 인스타그램 자동 로그인 & 좋아요 기능을 더 추가하고, 다음 피드로 이동시

private.tistory.com

인스타그램 자동 댓글 1편

 

[파이썬(Python)] 인스타그램 자동 프로그램 만들기 - 자동 댓글 (1)

파이썬 인스타그램 자동화 - 자동 댓글 작성하기 파이썬으로 인스타그램 자동 프로그램 만들기! 드디어 댓글 기능 구현입니다. 자동 프로그램이 좋아요만 해주면 의미가 없겠죠? 댓글에 이어 팔

private.tistory.com

 

작업환경

윈도우10, VS Code, Python3, Chrome88

 

프로그램 구동 화면

 

댓글 작성 확인 기능 추가

#9. 이미 댓글을 작성했는지 확인
div = driver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
comm_area = div.find_element_by_tag_name('div')
ul = div.find_element_by_tag_name('ul')
ul1 = ul.find_elements_by_class_name('Mr508') #9-1. 현재보여지는 댓글개수

if len(ul1) >= 12:
  while True:
    #9-2. 보여지는 댓글개수가 11개가 넘으면 끝까지 스크롤
    driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", ul)
    time.sleep(random.randint(500, 1000)/1000)

    before_comm_cnt = len(ul1)#9-3. 더보기 버튼 클릭 하기 전 보여지는 댓글개수
    time.sleep(2)
    #댓글 더 보기 버튼
    add_btn = ul.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/li')
    add_btn.click()
    time.sleep(2)

    div = driver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
    comm_area = div.find_element_by_tag_name('div')
    ul = div.find_element_by_tag_name('ul')
    ul1 = ul.find_elements_by_class_name('Mr508') # 9-4. 더보기 버튼 클릭 한 후 보여지는 댓글개수
    after_comm_cnt = len(ul1)#현재보여지는 댓글개수
	
    #9-5. 이전 댓글과 현재 댓글수가 같으면 정지, 같지 않으면 이전 댓글수에 입력
    if before_comm_cnt == after_comm_cnt:
      break
    else:
      before_comm_cnt += after_comm_cnt 
      
    break
# 9-6. 댓글 목록에 내 아이디가 있는지 확인
user = ul.find_element_by_link_text(insta_id)
print('이미 댓글을 작성한 피드입니다.')

9, 9-1, 9-2. 이미 댓글을 작성했는지 확인하려면 댓글 전체 목록을 확인해야겠죠? 하지만 인스타그램의 댓글은 11개가 넘으면 더보기 버튼을 클릭해야 나머지 댓글도 볼 수가 있습니다. 처음에 보여지는 댓글 개수를 확인한 후 (9-1) 11개 이상이면 댓글 제일 아래로 스크롤 한 후 + 버튼을 클릭해야 합니다.

9-3, 9-4. + 버튼 클릭 하기전! before_comm_cnt 에 현재 보여지는 댓글 개수를 넣어준뒤에 + 버튼을 클릭합니다. 그리고 클릭하고 난 뒤에 댓글 개수를 after_comm_cnt 에 넣어줍니다.

9-5. 이전 댓글수(before_comm_cnt)와 현재 댓글수(after_comm_cnt)를 비교하여 작업을 멈출지 계속 이어갈지 정해야합니다. 더 보기 버튼을 클릭해도 이전 댓글수와 현재댓글 수가 같으면 더 이상 스크롤 + 더보기 클릭 작업을 하지 않아도 되니 break를 통해 반복문을 빠져나와 주면되겠죠? 반대로 같지 않다면 before_comm_cnt 에 현재 댓글수를 넣어주고 스크롤 + 더보기 작업을 계속 반복해줍니다. 

9-6. 댓글이 모두 보이게 되면 댓글 목록에서 처음 선언한 변수에 있는 나의 인스타그램 아이디로 된 링크가 있는지 확인해줍니다. 이 부분에서 NoSuchElementException 에러가 발생하지 않는다면 이미 작성된 댓글이 있다는 뜻이겠죠!

 

 

댓글 작성 확인 후 댓글 작성하기

NoSuchElementException 에러가 발생하지 않았을때 이미 작성한 댓글이 있는거라면, 만약 이미 작성한 댓글이 없을때는 에러가 난다는 뜻일까요??

맞습니다 ㅎㅎ. 그래서 이 부분을 try ~ except 처리하여 에러가 발생할 경우 댓글을 작성하도록 구현하면 됩니다. 물론 지난 강의에서 작성했던 소스와는 달라지겠죠? 아래의 전체 소스코드에서 확인해주세요 :)

 

테스트 방법

댓글 중복 확인 기능을 테스트하기에 딱 좋은 방법은 '인기피드순'으로 작업 한 뒤에 다시 '인기피드순'으로 작업하는겁니다. 최신피드순으로 작업을 하게되면 피드가 자주 바뀌어 확인하기 힘드니 해당 기능을 확인하고 싶은분들은 '인기피드순'으로 테스트해보세요.

 

혹시나해서! 주의사항 

인스타그램은 정해진 시간동안 볼 수 있는 데이터(피드, 댓글, 팔로워 등)양이 정해져 있습니다. 이 정해진 양을 넘기게 되면 해당 데이터는 일정시간동안 보여지지 않고 무한로딩이 되어버립니다. 그렇기때문에 댓글 목록을 확인할때 댓글 로딩도 기다릴겸 time.sleep으로 약간의 대기시간을 설정해두었습니다.

혹시나 대기시간을 제거하실 분들은 참고하시길 바랍니다.

 

 

전체 소스코드

# -*- coding: utf-8 -*-

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import inspect, os, platform, time, random

def bot():
    #필요한 변수 정의
    insta_id = '인스타그램아이디'
    insta_pw = '인스타그램패스워드'
    insta_tag = '개냥이(#제외)'
    insta_cnt = int(input('작업횟수(숫자만) : '))
    insta_sort = '0' # '0' = 인기게시물에 작업, '1' = 최근게시물에 작업
    ## 댓글
    insta_comm = ['넘 귀여워요!', '꺄 귀여워요! 잘 보고갑니다!', '귀염귀염 :)']


    #크롬드라이버 로딩
    options = webdriver.ChromeOptions()
    options.add_argument('--disable-gpu')
    options.add_argument('user-agent=Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36')

    current_folder = os.path.realpath(
                os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))

    if platform.system() == 'Windows':
        driver_path = os.path.join(current_folder, 'chromedriver.exe')
    else:
        driver_path = os.path.join(current_folder, 'chromedriver')

    driver = webdriver.Chrome(driver_path, options=options)
    driver.implicitly_wait(10)

    
    ### 인스타그램 자동 좋아요 작업 ###
    
    # 1. 인스타그램 로그인 페이지로 이동
    driver.get('https://www.instagram.com/?hl=ko')
    print('로그인중....')
    time.sleep(3)

    # 2. 아이디 입력창을 찾아서 위에서 입력받은 아이디(insta_id)값 입력
    id_input = driver.find_element_by_xpath('//*[@id="loginForm"]/div/div[1]/div/label')
    id_input.click() #입력창 클릭
    id_input.send_keys(insta_id) #아이디 입력


    # 2-1. 패스워드 입력창을 찾아서 위에서 입력받은 패스워드(insta_pw)값 입력
    pw_input = driver.find_element_by_xpath('//*[@id="loginForm"]/div/div[2]/div/label')
    pw_input.click()
    pw_input.send_keys(insta_pw)

    # 3. 로그인 버튼 클릭
    login_btn = driver.find_element_by_xpath('//*[@id="loginForm"]/div/div[3]/button')
    login_btn.click()


    # 잠시 대기
    time.sleep(3)


    # 4. 작업할 해시태그 검색 결과 페이지로 이동
    driver.get('https://www.instagram.com/explore/tags/{}/'.format(insta_tag))
    time.sleep(2)

    # 5. 인기게시물 혹은 최근게시물 첫번째 피드 선택
    if insta_sort == '0':
        #인기게시물 첫번째 피트 선택
        hot_first_feed = driver.find_element_by_xpath('//*[@id="react-root"]/section/main/article/div[1]/div/div/div[1]/div[1]/a/div/div[2]')
        hot_first_feed.click()
    else:
        #최근게시물 첫번째 피드 선택
        new_first_feed = driver.find_element_by_xpath('//*[@id="react-root"]/section/main/article/div[2]/div/div[1]/div[1]/a/div[1]/div[2]')
        new_first_feed.click()
    
    time.sleep(1)

    # 6. 좋아요 작업 - 입력한 횟수만큼 반복 작업
    for idx in range(insta_cnt):
        div = driver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div')
        div = div.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
        like_btn = div.find_element_by_tag_name('button') #좋아요 버튼

        btn_svg = like_btn.find_element_by_tag_name('svg')
        svg_txt = btn_svg.get_attribute('aria-label')

        if svg_txt != '좋아요':
            print('이미 좋아요 작업한 피드')
        else:
            like_btn.click() #좋아요 클릭
            print('{}번째 피드 좋아요 작업 완료'.format(idx + 1))

        # 너무 빠르게 작업을 할 경우 많은 양의 작업을 하게 되어 인스타그램측에서 계정 정지나 경고를 할 수 있으니
        # 작업과 다음 작업 사이의 속도를 조절하기 위해 20초 이상을 설정해주세요.
        time.sleep(5)

        # 7. 좋아요 작업 - 다음 피드로 이동 -> 댓글 작성 아래로...


        #9. 이미 댓글을 작성했는지 확인
        div = driver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
        comm_area = div.find_element_by_tag_name('div')
        ul = div.find_element_by_tag_name('ul')
        ul1 = ul.find_elements_by_class_name('Mr508') #9-1. 현재보여지는 댓글개수
        try:
            if len(ul1) >= 12:
                while True:
                    #9-2. 보여지는 댓글개수가 11개가 넘으면 끝까지 스크롤
                    driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", ul)
                    time.sleep(random.randint(500, 1000)/1000)

                    try:
                        before_comm_cnt = len(ul1)#9-3. 더보기 버튼 클릭 하기 전 보여지는 댓글개수
                        time.sleep(2)
                        #댓글 더 보기 버튼
                        add_btn = ul.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/li')
                        add_btn.click()
                        time.sleep(2)

                        div = driver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
                        comm_area = div.find_element_by_tag_name('div')
                        ul = div.find_element_by_tag_name('ul')
                        ul1 = ul.find_elements_by_class_name('Mr508') # 9-4. 더보기 버튼 클릭 한 후 보여지는 댓글개수
                        after_comm_cnt = len(ul1)#현재보여지는 댓글개수
                        
                        #9-5. 이전 댓글과 현재 댓글수가 같으면 정지, 같지 않으면 이전 댓글수에 입력
                        if before_comm_cnt == after_comm_cnt:
                            break
                        else:
                            before_comm_cnt += after_comm_cnt 
                    except NoSuchElementException as ne:
                            break
            # 9-6. 댓글 목록에 내 아이디가 있는지 확인
            user = ul.find_element_by_link_text(insta_id)
            print('이미 댓글을 작성한 피드입니다.')
        except NoSuchElementException as n:
            #8. 댓글 작성 영역 찾기
            div = driver.find_element_by_xpath('/html/body/div[5]/div[2]')
            div1 = div.find_element_by_xpath('/html/body/div[5]/div[2]/div')
            article = div1.find_element_by_xpath('/html/body/div[5]/div[2]/div/article')
            div2 = article.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]')
            section = div2.find_element_by_css_selector('div.eo2As > section.sH9wk._JgwE') 
            ta = section.find_element_by_tag_name('textarea')

            time.sleep(2)

            #8-1. 댓글 작성 영역으로 이동해 댓글창 클릭
            ac = ActionChains(driver) 
            ac.move_to_element(ta) 
            ac.click() 
            ac.pause(2) 

            #8-2. 여러개의 댓글 중 랜덤으로 선택
            choice_comm = (random.choice(insta_comm))
            comm = choice_comm.split('\n')

            #8-3. 댓글 작성
            for i, c in enumerate(comm):
                c = c.replace("\n", "")
                ac.send_keys(c)        
                i += 1
                #8.4. 댓글이 여러줄일 경우 Shift + Enter로 다음 줄 이동
                if i < len(comm):
                    ac.key_down(Keys.SHIFT).send_keys(Keys.ENTER).key_up(Keys.SHIFT)

            ac.pause(2) 
            ac.send_keys(Keys.ENTER) 

            #8-5. 등록한 ac 실행
            ac.perform()

            print('댓글 작성 성공 - {}'.format(choice_comm))
            time.sleep(5)

        # 7. 좋아요 + 댓글 작업 완료 후 다음 피드 이동
        if idx < insta_cnt:
            try:
                next_feed = driver.find_element_by_link_text('다음')
                next_feed.click()
            except NoSuchElementException as n:
                print('피드 개수 부족으로 작업이 종료됩니다.')
                break


    print('모든 작업 완료')
    driver.quit()


bot()



 

다음 포스팅에서 구현할 기능

  • 인스타그램 자동 팔로우

 

공감과 댓글은 작성자에게 많은 힘이됩니다. 감사합니다😄

반응형

댓글

💲 추천 글