[Python] 인스타그램 좋아요 매크로 업그레이드- opencv
어제 다전공 자기소개서를 쓰는데, 프로젝트 기입란이 있었다.
어디 내놓기 부끄럽지만 그래도 조그만 프로젝트를 해왔던 나...
인스타그램 좋아요 프로그램을 기입하는데 뭔가 걸렸다.
사실 저번에 제작했던 프로그램은 단점이 조금 있었다. 무작정 element를 찾아서 버튼을 누르는 방식이다 보니까,
이미 좋아요가 눌려 있는 사진의 경우에는 좋아요 취소가 되는 상황이...
그래서 얼마 전에 새로 습득한 pyautogui라는 프로그램으로 보수작업을 해보기로 마음먹었다.
기본적인 방법은 이전 게시물과 같다!
https://brianhyun.tistory.com/8
이제 여기에서 버튼을 누를 때의 수행문만 변경할 것이다.
1.준비
시작하기에 앞서 pyintergui에 대해서 알아보자면, 얘는 이미지나 좌표 기반으로 주어진 명령을 수행할 수 있는 모듈이다. 클릭, 키 입력 같은 게 가능하다. 그래서 데스크탑 자동화에 되게 용이하다.
그런데 이미지나 좌표 기반이라는 말은, 셀레니움같은 동적 웹 자동화에서도 써먹을 수 있다는 말이다.
한 번 코드에 적용시켜보자.
import pyautogui
yautogui를 사용하려면 이렇게 import 해주면 된다.
그리고 mac으로 갈아타면서 제일 골치아팠던 게 환경변수(PATH) 등록이었다. 훗날 한 번 포스팅을 하고 싶은데,
zshell을 이용하는 나의 경우 bash 쉘에 등록하고 유난을 떨다가 실패한 전적이 있어서,
그러기엔 난 나를 못 믿는다 하는 맥 이용자가 있다면
driver = webdriver.Chrome(executable_path='/Users/gohyun/Desktop/chromedriver')
이런 식으로 executable_path=파일경로 로 써주면 된다.
이제 좋아요 버튼을 누르는 부분을 수정해보자.
원래는
driver.find_elements_by_class_name('wpO6b')[1].click()
이런 식으로 셀레니움만을 이용해서 특정 조건에 맞는 버튼을 찾아서 눌러줬다.
(후에 알았지만 xpath를 쓰는게 굉장히 편하다. 이것도 포스팅 컨텐츠.)
요 부분을 우리가 설정한 이미지일 경우에만 누르도록 수정해주면 되는 것.
def Click():
global count
time.sleep(2)
driver.find_elements_by_class_name('wpO6b')[1].click()
driver.find_elements_by_class_name('_65Bje')[0].click()
time.sleep(2)
count += 1
print('현재 좋아요 개수 : {0}'.format(count))
원래의 클릭 함수이다. 단순히 element를 찾아서 누르는 행위만 반복하는 함수. 이러다 보니 좋아요가 눌려 있어도 다시 눌러 취소시켜버린다.
이것을
def Click():
global count
element = pyautogui.locateCenterOnScreen('/Users/gohyun/Desktop/Project/instagram_like/like_blank.png')
if element:
pyautogui.click(element[0]/2, element[1]/2)
count += 1
print('현재 좋아요 개수 : {0}'.format(count))
else:
print('이미 좋아요가 눌린 포스트입니다.')
driver.find_elements_by_class_name('_65Bje')[0].click() #다음 버튼 클릭
이렇게 바꿔줄 것이다. 위에서부터 찬찬히 살펴보자면 pyautogui.locateCenteronScreen은 말 그대로
'스크린 위에서 입력한 값에 해당하는 것의 가운데 위치를 [x,y] 형태로 돌려주는 것'이다.
그러니까 이거를 위해서는 우리가 좋아요가 눌리지 않은 하트의 이미지를 이놈에게 할당해줄 필요가 있다.
인스타그램에 들어가서 캡쳐하자.
Windows의 경우 Printscr를 누르고 그림판에 들어가서 붙여넣기(Ctrl+v), 해당 부분만 선택 뒤에 Ctrl+x를 하면 자르기가 된다. 그거를 새 파일에 다시 붙여넣기 해주고 크기를 조정해주면 된다.
Mac의 경우에는 command+shift+4를 동시에 눌러주면 된다. 그러면 자동으로 선택한 부분이 잘라내기되어 데스크탑에 저장된다.
(주의! pyautogui에서는 무조건 이미지를 png로 줘야 한다.)
그리고 locateCenteronscreen의 인자로 그 위치를 넣어주면 된다. 프로그램과 이미지가 같은 폴더에 있으면 이름만 넣어줘도 되고.
이제 다 끝났다. 그 밑의 조건문은 단순하다.
if element: 엘리먼트가 존재하면, pyautogui.click(x,y)좌표 식으로 써준다.
Retina 디스플레이를 사용하는 경우 좌표가 두배가 되어 나오므로, 나는 나누기 2를 해줬다.
Windows의 경우에는 /2를 안 써줘도 된다.
누르고 카운트 계수를 늘려주면 끝!
이렇게 되면 이미지 element가 존재하지 않을 수도 있다. 이미 좋아요가 눌린 게시물이 이에 해당한다.
이 경우는 else로 두고, '이미 좋아요를 누른 포스트입니다'를 프린트해준다.
그리고 함수의 마지막에 다음 버튼을 눌러주면 끝.
최종적인 코드는
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import random
import pyautogui
#드라이버 정의
driver = webdriver.Chrome(executable_path='/Users/gohyun/Desktop/chromedriver')
#If Chromedriver is exe and there's a PATH error message, use executable_path variable.
#인스타그램 접속
driver.get('https://instagram.com')
driver.implicitly_wait(5)
#로그인
e = driver.find_elements_by_class_name('_2hvTZ')[0] #로그인 아이디 창 element 찾기
e.send_keys('인스타그램 아이디')
e = driver.find_elements_by_class_name('_2hvTZ')[1] #로그인 비밀번호 창 element 찾기
e.send_keys('인스타그램 비밀번호')
e.send_keys(Keys.ENTER)
time.sleep(5)
#페이지 이동 - driver.get 괄호 안에 태그 검색한 주소 붙여넣기
driver.get('https://www.instagram.com/explore/tags/%EC%A2%8B%EB%B0%98/')
driver.implicitly_wait(5)
driver.find_elements_by_class_name('v1Nh3')[0].click() #검색 결과 첫 게시물 누르기
count = 0 #누른 좋아요 개수를 세줄 카운터
def Click():
global count
element = pyautogui.locateCenterOnScreen('/Users/gohyun/Desktop/Project/instagram_like/like_blank.png')
if element:
pyautogui.click(element[0]/2, element[1]/2)
count += 1
print('현재 좋아요 개수 : {0}'.format(count))
else:
print('이미 좋아요가 눌린 포스트입니다.')
driver.find_elements_by_class_name('_65Bje')[0].click() #다음 버튼 클릭
#실행
while True:
try :
i = random.randrange(1,16)
time.sleep(i)
Click()
time.sleep(2)
except Exception as e:
print(e)
print('에러가 발생하여 프로그램을 종료합니다. 에러명:{}.\n총 좋아요 개수: {}개'.format(e, count))
driver.close()
break
이렇게 pyautogui를 통하여 이미지 인식을 기반으로 인스타그램 좋아요 프로그램을 업그레이드 해봤다.
처음에는 되게 복잡하다고 생각했는데, 까보니까 별거 없다. 역시 인생은 자신감이다.
앞으로도 쫄지 말고 공부 열심히 하자 ㅋㅋㅋㅋ