지금은 코드도 많이 바뀌었고, 애초에 인스타그램과 같은 소셜 미디어는 정형화된 패턴을 읽어내서 행동하는 주체가 사람인지 기계인지 파악합니다. 그렇기 때문에 아래 코드로 제대로된 인스타그램 봇을 만들지는 못합니다. 참고로만 보세요.


안녕하세요. 오늘은 인스타그램에서 원하는 태그의 최신 게시물에 자동으로 좋아요를 눌러주는 매크로, 즉 인스타그램 좋아요 봇을 만들어보도록 하겠습니다. 오늘 사용할 모듈은 selenium, webdriver-manager, random, time, datetime입니다. random과 time, datetime 모듈은 일반적으로 설치되어 있으므로, selenium과 webdriver-manager를 설치해주시면 됩니다.

1. 필요한 모듈 불러오기

우선 필요한 모듈을 불러오겠습니다. 저는 Microsoft Edge를 사용하기 때문에 webdriver-manager로 EdgeChromiumDriverManager를 import했습니다. 다른 브라우저를 쓰시는 분은 다른 브라우저를 import 하시면 되겠습니다.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from random import randint
import time
from datetime import datetime

2. 인스타그램 로그인하기

먼저 인스타그램을 로그인하겠습니다. 로그인 할 인스타그램 ID와 PW를 입력하고, 인스타그램을 실행합니다. 실행된 인스타그램 창에 로그인 할 인스타그램 아이디와 패스워드를 입력하고 로그인하면 됩니다. 인스타그램에 로그인하면 정보저장 팝업과 알림설정 팝업이 실행되기 때문에, 두 팝업을 꺼주겠습니다.

#인스타그램 아이디 및 패스워드 입력
ID = input('인스타그램 ID를 입력하세요. : ')
PW = input('인스타그램 PW를 입력하세요. : ')
 
#인스타그램 실행하기
browser = webdriver.Edge(EdgeChromiumDriverManager().install())
browser.get("https://instagram.com")
time.sleep(10) #로딩하는 시간 10초를 기다려줍니다.
 
#인스타그램 아이디 입력하기
username = browser.find_element_by_name('username') #인스타그램 아이디 입력란을 찾아줍니다.
username.send_keys(ID) #인스타그램 아이디를 입력해줍니다.
 
#인스타그램 패스워드 입력하기
password = browser.find_element_by_name('password') #인스타그램 패스워드 입력란을 찾아줍니다.
password.send_keys(PW) #인스타그램 패스워드를 입력해줍니다.
 
#인스타그램 로그인하기
password.send_keys(Keys.RETURN) #인스타그램에 로그인합니다.
time.sleep(10)
 
#정보저장 팝업 닫기
popup = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/div/div/button')
popup.send_keys(Keys.ENTER)
time.sleep(10)
 
#알림설정 팝업 닫기
popup = browser.find_element_by_xpath('/html/body/div[4]/div/div/div/div[3]/button[2]')
popup.send_keys(Keys.ENTER)

3. 필요한 함수 만들기

본격적으로 인스타그램 좋아요 봇을 만들기 전에 함수의 복잡함을 완화해줄 수 있도록, 함수를 만들도록 하겠습니다. 만들 함수는 선택한 게시물에서 다음 게시물로 이동하는 함수와, 검색한 태그의 최근 게시물을 선택하는 함수입니다.

1) 다음 게시물로 이동하는 함수 만들기

다음 게시물로 이동하는 함수입니다. ‘time.sleep(randint(1000,2000)/1000)‘부분은 다음 게시물로 이동하기 전에 약간의 시간을 두기 위해서 추가한 것입니다. 불필요하다고 생각되시면 제외하거나 임의 값으로 입력된 시간을 고정 값으로 변경하셔도 무방합니다.

#함수 만들기 : 다음 게시물로 이동
def selectNext():
     time.sleep(randint(1000,2000)/1000)
     nextFeed = browser.find_element_by_css_selector('body > div._2dDPU.CkGkG > div.EfHg9 > div > div > a._65Bje.coreSpriteRightPaginationArrow')
     nextFeed.click() 

2) 최근 게시물 선택하는 함수 만들기

다음은 최근 게시물을 선택하는 함수입니다. 인스타그램 태그를 검색하면, 맨 위의 3줄은 그 태그의 인기 게시글이고, 그 이후부터 최근 게시물입니다. 그래서 인기 게시글의 마지막 게시글을 선택하고, 다음 게시물로 이동하여 최근 게시물을 선택하도록 하겠습니다. 처음부터 4줄 첫번째에 있는 최근 게시글을 선택하지 않는 이유는 인기 게시글 마지막을 선택하는 게 게시글 위치를 특정하기 더 쉽기 때문입니다.

#함수 만들기 : 최근 게시물 선택하기
def selectFirst():
    feed = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/article/div[1]/div/div/div[3]/div[3]/a')
    feed.send_keys(Keys.ENTER)
    selectNext()

4. 반복해서 좋아요 누르기

이제 준비는 다 끝났습니다. 그러면 이제 설정한 태그의 최신 게시물에 좋아요를 누르는 봇을 만들도록 하겠습니다. 지금부터 만들 봇은 설정한 태그의 최신 게시글부터 오래된 게시글 순으로 설정된 횟수만큼 좋아요를 누릅니다. 설정된 횟수가 종료가 되면, 다음 태그를 불러와 똑같은 작업을 반복합니다. 좋아요를 누를 때마다 좋아요를 누른 횟수가 올라가며, 사전에 설정한 횟수를 채우면, 봇이 멈춥니다. 그리고 인스타그램은 하루에 누를 수 있는 좋아요 수에 제한이 있기 때문에, 광고는 최대한 피할 수 있도록 필터링 문구가 있는 게시글은 좋아요를 누르지 않고 넘어갑니다.

1) 원하는 태그와 필터링 문구 입력하기

우선은 좋아요를 누를 태그와 필터링 할 문구를 설정하도록 하겠습니다. 태그와 필터링 문구는 리스트 형태로 입력합니다. 필터링 문구는 태그 중 특정 문구가 있는지 검색하는 것이 아니라, 인스타그램 게시글 본문 중 특정 문구가 있는지 필터링합니다. 필터링 없이 모든 게시물에 좋아요를 누르게 되면, 인스타그램에 광고가 많기 때문에, 광고글에 좋아요를 누르고 있는 모습을 발견할 수 있습니다. 하루에 누를 수 있는 좋아요 숫자는 한정되어 있으므로, 최대한 효율적으로 사용할 수 있도록, 광고는 걸러줍니다.

#검색 태그와 필터링 태그를 입력하기
tags = input("원하는 태그를 입력하세요. 구분자는 ,입니다. (예)고양이, 벵갈, 먼치킨 : ").split(',')
block_tags = input("필터링 할 문자열을 입력하세요. 구분자는 ,입니다. : ").split(',')

tags에 입력한 태그 리스트는 좋아요를 누르기를 바라는 태그 검색화면으로 이동하는데 활용됩니다. ‘for tag in tags’를 활용해서 tags에 있는 순서대로 ‘browser.get(‘https://www.instagram.com/explore/tags/’ + tag)‘를 이용해서 이동하도록 합니다. 그리고 사전에 설정한 함수 selectFirst()를 이용해서, 검색 결과의 첫번째 최근 게시물을 선택합니다.

for tag in tags:
    browser.get('https://www.instagram.com/explore/tags/' + tag)
    time.sleep(10)
    selectFirst()

‘block_tags’에 입력한 문구(태그가 아니라 문구, 수정이 귀찮아서 그대로 사용)는 인스타그램 본문에 특정 문구가 있는지 검색합니다. 만약 특정 문구가 있다면, 다음 게시글로 넘어가서 다시 특정 문구가 있는지 검색합니다.

우선은 ‘while True’를 이용해서 계속 반복하는 순환함수를 생성합니다. 인스타그램 본문은 ‘browser.find_element_by_xpath(‘/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/div/li/div/div/div[2]/span’).text’입니다. 하지만, 인스타그램 본문 위치가 다른 경우가 있기 때문에, 위 명령어에 에러가 발생할 수 있습니다. 이를 방지하기 위해서 ‘try’와 ‘except’를 사용해서 에러가 발생하면 순환함수(while True)에서 빠져나와 다음 함수로 넘어갈 수 있도록 합니다.

인스타그램 본문(content로 명명)에 특정 문구(tag)가 있으면, ‘block’을 ‘True’로 변경하고, 다음 게시물로 이동합니다. 이때 제대로 필터링이 작동하는지 확인하기 위해서 필터링된 문구와 게시물 링크를 출력합니다. 만약 ‘block_tags’에 있는 모든 문구가 ‘content’에 없으면, ‘block’은 ‘False’ 상태를 유지하고 ‘try’반복문은 끝나게 됩니다. ‘try’반복문이 끝난 후 ‘block’ 상태를 확인해서 ‘block’이 ‘True’면 순환함수(while True)를 다시 반복하고, ‘block’이 ‘False’면 순환함수를 종료하도록 합니다.

while True:
    block = False
    try:
        time.sleep(2)
        content = browser.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/div/li/div/div/div[2]/span').text
        for tag in block_tags:
            if tag in content:
                block = True
                print('광고! (필터: {}, 링크: {}, 시간: {})'.format(tag, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
                selectNext()
                break
    except:
        break
    if block == False:
        break
 

2) 게시글에 좋아요 누르기

필터링이 완료되면, 특정 게시물이 떠있는 상태가 됩니다. 이제 이 게시물에 좋아요를 누르도록 하겠습니다. 태그를 통해 최근 게시물을 검색하다 보면, 동일한 게시글이 반복해서 나오는 경우가 있는데, 이 경우 좋아요를 2번 눌러서 취소가 되므로, 이미 좋아요가 눌러진 게시글은 넘어가도록 하겠습니다.

‘browser.find_elements’를 이용해서 좋아요 버튼과 좋아요를 눌렀는지 여부를 확인할 수 있는 요소를 각각 ‘like_button’과 ‘like_check’에 할당합니다. ‘like_pass’는 우선 ‘False’로 설정해줍니다. 먼저 좋아요가 이미 눌러져 있는지 확인합니다. ‘like_check’의 요소들을 검사해서 ‘좋아요 취소’라는 문구가 있으면, 좋아요가 눌러져 있는 것입니다. 만약 ‘좋아요 취소’ 문구가 있다면, ‘like_pass’는 ‘True’로 변경하고 반복문을 종료합니다.

만약 ‘좋아요 취소’ 문구를 찾지 못하였다면, ‘like_pass’는 ‘False’상태로 유지됩니다. 이 경우 ‘like_button[0].click()‘를 통해 좋아요를 눌러주도록 합니다. 좋아요를 눌러줄 때도 앞서 특정 문구를 필터링할 때와 동일하게, 좋아요를 누른 게시글 링크를 포함한 정보를 프린트합니다. 만약, 이 과정에서 오류가 날 경우 “Exception!”문구와 함께 넘어가도록 합니다.

#좋아요 누르기
try:
    like_button = browser.find_elements_by_xpath('//article//section/span/button')
    like_check = browser.find_elements_by_class_name('_8-yf5 ')
 
    like_pass = False
 
    for i in range(len(like_check)):
        if like_check[i].get_attribute("aria-label") == '좋아요 취소' :
            like_pass = True
            print("Pass~")
            break
 
    if like_pass == False :
        like_button[0].click() #list 중 0번째 버튼을 선택
        like_count+=1
        print('Like♥ {}번(링크: {}, 시간: {})'.format(like_count, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
except :
    print ("Exception!")
time.sleep(2)
selectNext()

3) 좋아요 누르는 횟수 설정하고 반복하기

이제 인스타그램 좋아요 봇을 만드는데 필요한 부분은 다 끝났습니다. 앞의 문구들을 적당히 배치해서 자동으로 좋아요를 누르도록 하겠습니다. ‘like_count’, ‘like_want’와 ‘refresh_count’를 이용해서 좋아요를 누를 총 횟수와 오류가 발생했을 때, 몇 번이나 반복문을 다시 실행할 것인지를 설정합니다. ‘like_want’는 원하는 숫자를 입력하시면 됩니다. 인스타그램은 일반적으로 하루에 1,200개 정도의 좋아요를 누를 수 있는 것으로 알려져 있으므로, 적당히 입력해 주시면 됩니다.

‘while like_count < like_want and refresh_count < 10’ 반복문을 통해서, ‘like_count’가 입력한 ‘like_want’에 도달하거나, ‘refresh_count’가 10에 도달하면 반복문을 멈추도록 합니다. 그리고 ‘for tag in tags’ 반복문을 이용해서 사전에 입력한 ‘tags’의 tag마다 반복되도록 합니다. 이때 태그별로 좋아요를 눌러주는 횟수를 설정할 필요가 있습니다. ‘for a in range(50)’ 반복문을 이용해서 한 태그에서 좋아요를 누르는 작업을 50회 진행하고, 다음 태그로 넘어가도록 설정했습니다. 이 부분은 사용하시는 태그의 게시글 수에 따라 적절하게 조절하시면 됩니다.

이후에는 앞서 설명한, 필터링 작업을 거치고 좋아요를 눌러주면 됩니다. 이 과정에서 로딩이 길어지거나 인스타그램에서 제한을 할 경우 에러가 발생할 수 있습니다. ‘except’를 통해서 에러가 발생하면, ‘while like_count < like_want and refresh_count < 10’ 반복문을 다시 실행하도록 하였습니다. 이를 통해 로딩이 길어지는 등의 이유로 에러가 발생하여, 인스타그램 봇이 멈추는 것을 방지하였습니다. 그리고 에러가 발생할 때마다 ‘refresh_count+=1’를 하여, 인스타그램에서 좋아요를 제한하는 등의 이유로 계속 에러가 반복될 경우 봇을 멈추도록 하였습니다.

#반복해서 좋아요 누르기
like_count=0
refresh_count=0
like_want = int(input("원하는 좋아요 횟수를 입력하세요. : ")) #좋아요를 눌러줄 횟수를 입력합니다.
while like_count < like_want and refresh_count < 10:
    try:
        for tag in tags:
            browser.get('https://www.instagram.com/explore/tags/' + tag)
            time.sleep(10)
            selectFirst()
            for a in range(50):
                while True:
                    block = False
                    try:
                        time.sleep(2)
                        content = browser.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/div/li/div/div/div[2]/span').text
                        for tag in block_tags:
                            if tag in content:
                                block = True
                                print('광고! (필터: {}, 링크: {}, 시간: {})'.format(tag, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
                                selectNext()
                                break
                    except:
                        break
                    if block == False:
                        break
                time.sleep(2)
                #좋아요 누르기
                try:
                    like_button = browser.find_elements_by_xpath('//article//section/span/button')
                    like_check = browser.find_elements_by_class_name('_8-yf5 ')
 
                    like_pass = False
 
                    for i in range(len(like_check)):
                        if like_check[i].get_attribute("aria-label") == '좋아요 취소' :
                            like_pass = True
                            print("Pass~")
                            break
 
                    if like_pass == False :
                        like_button[0].click() #list 중 0번째 버튼을 선택
                        like_count+=1
                        print('Like♥ {}번(링크: {}, 시간: {})'.format(like_count, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
                except :
                    print ("Exception!")
                time.sleep(2)
                selectNext()
    except:
        refresh_count+=1
        print("refresh: {}".format(refresh_count)) #페이지 로딩이 길어지는 등 오류가 발생하면 처음으로 돌아가서 다시 매크로를 실행합니다.

5. 코드전문

이것으로 파이썬으로 인스타그램 좋아요 봇을 만드는 방법을 알아보았습니다. 아래는 코드 전문입니다. 여기서는 input으로 처리하였으나, 저는 주기적으로 반복해서 실행하거나 좀 더 다양한 옵션을 주기 위해 input을 사용하지 않습니다. 그리고 텔레그램을 활용해서 중간중간 프로세스 상태나 완료 여부를 파악할 수 있도록 했습니다. 그리고 자동으로 댓글을 남기거나 팔로우를 하는 방법도 있습니다. 나중에 시간이 있을 때 댓글이랑 팔로우 방법도 남기도록 하겠습니다.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from random import randint
import time
from datetime import datetime
 
#인스타그램 아이디 및 패스워드 입력
ID = input('인스타그램 ID를 입력하세요. : ')
PW = input('인스타그램 PW를 입력하세요. : ')
 
#인스타그램 실행하기
browser = webdriver.Edge(EdgeChromiumDriverManager().install())
browser.get("https://instagram.com")
time.sleep(10) #로딩하는 시간 10초를 기다려줍니다.
 
#인스타그램 아이디 입력하기
username = browser.find_element_by_name('username') #인스타그램 아이디 입력란을 찾아줍니다.
username.send_keys(ID) #인스타그램 아이디를 입력해줍니다.
 
#인스타그램 패스워드 입력하기
password = browser.find_element_by_name('password') #인스타그램 패스워드 입력란을 찾아줍니다.
password.send_keys(PW) #인스타그램 패스워드를 입력해줍니다.
 
#인스타그램 로그인하기
password.send_keys(Keys.RETURN) #인스타그램에 로그인합니다.
time.sleep(10)
 
#정보저장 팝업 닫기
popup = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/div/div/button')
popup.send_keys(Keys.ENTER)
time.sleep(10)
 
#알림설정 팝업 닫기
popup = browser.find_element_by_xpath('/html/body/div[4]/div/div/div/div[3]/button[2]')
popup.send_keys(Keys.ENTER)
 
#함수 만들기 : 다음 게시물로 이동
def selectNext():
     time.sleep(randint(1000,2000)/1000)
     nextFeed = browser.find_element_by_css_selector('body > div._2dDPU.CkGkG > div.EfHg9 > div > div > a._65Bje.coreSpriteRightPaginationArrow')
     nextFeed.click() 
 
#함수 만들기 : 최근 게시물 선택하기
def selectFirst():
    feed = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/article/div[1]/div/div/div[3]/div[3]/a')
    feed.send_keys(Keys.ENTER)
    selectNext()
 
#검색 태그와 필터링 태그를 입력하기
tags = input("원하는 태그를 입력하세요. 구분자는 ,입니다. (예)고양이, 벵갈, 먼치킨 : ").split(',')
block_tags = input("필터링 할 문자열을 입력하세요. 구분자는 ,입니다. : ").split(',')
 
#반복해서 좋아요 누르기
like_count=0
refresh_count=0
like_want = int(input("원하는 좋아요 횟수를 입력하세요. : ")) #좋아요를 눌러줄 횟수를 입력합니다.
while like_count < like_want and refresh_count < 10:
    try:
        for tag in tags:
            browser.get('https://www.instagram.com/explore/tags/' + tag)
            time.sleep(10)
            selectFirst()
            for a in range(50):
                while True:
                    block = False
                    try:
                        time.sleep(2)
                        content = browser.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/div[1]/ul/div/li/div/div/div[2]/span').text
                        for tag in block_tags:
                            if tag in content:
                                block = True
                                print('광고! (필터: {}, 링크: {}, 시간: {})'.format(tag, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
                                selectNext()
                                break
                    except:
                        break
                    if block == False:
                        break
                time.sleep(2)
                #좋아요 누르기
                try:
                    like_button = browser.find_elements_by_xpath('//article//section/span/button')
                    like_check = browser.find_elements_by_class_name('_8-yf5 ')
 
                    like_pass = False
 
                    for i in range(len(like_check)):
                        if like_check[i].get_attribute("aria-label") == '좋아요 취소' :
                            like_pass = True
                            print("Pass~")
                            break
 
                    if like_pass == False :
                        like_button[0].click() #list 중 0번째 버튼을 선택
                        like_count+=1
                        print('Like♥ {}번(링크: {}, 시간: {})'.format(like_count, browser.current_url, datetime.now().strftime('%Y.%m.%d %H:%M:%S')))
                except :
                    print ("Exception!")
                time.sleep(2)
                selectNext()
    except:
        refresh_count+=1
        print("refresh: {}".format(refresh_count)) #페이지 로딩이 길어지는 등 오류가 발생하면 처음으로 돌아가서 다시 매크로를 실행합니다.
 
print('Finish Bot! Total Like = {}'.format(like_count)) #매크로 작동이 종료되면, 종료 메세지를 출력합니다.