숫자가 커질수록 연산과정이 많아져서 '이거 루프 도는 건가?'라고 생각할때 즈음 결과값이 나오는 것을 보았다.
그렇다면 어떻게 개선해야하는 것인가?
- 알고리즘을 생각하고 개선 포인트를 찾자
- for문이 3번 들어가기 때문에 for문 번수 * for문 번수 * for문 번수 이기 때문에 for문을 1개만 줄여도 '마지막 for문 번수'만큼을 안 곱해도 된다.
[피타고라스 삼조 코딩 - 비효율적]
for a in range(1, 400):
a2 = a * a
for b in range(1, 400):
b2 = b * b
for c in range(1, 400):
c2 = c * c
if a2 + b2 == c2:
if a + b+ c == 400:
#print(a, b, c)
print(a*b*c)
[피타고라스 삼조 코딩 - 효율적으로 개선]
- for문을 1개 없애서 결과값 속도가 훨씬 빨라졌다.
'c = 400 - a - b'와 같이 표현할 수 있다는 것을 배웠다.
for a in range(1, 400):
for b in range(1, 400):
c = 400 - a - b
if a*a + b*b == c*c:
if a + b + c == 400 and a < b < c:
print(a, b, c)
print(a*b*c)
** 이 문제는 a + b + c 가 400이면서 피타고라스 삼조를 만족시키는 샘플 문제에 대한 코딩이다.
그에 대한 코드이다. (아이디, 패스워드를 하드코딩하는 이유는 exe 파일로 만들어서 바로 스케쥴링 걸수있도록)
[개선 포인트]
- 친절한 안내 : 총 갯수, 선택 해시태그, 몇초후 시작, 종료되었습니다
- 컨텐츠 작업 : 랜덤
- 해시태그 선택 : 랜덤
- 좋아요작업 다음피드 : 랜덤으로 이동 (random.randint 모듈 사용)
=> 실제 인스타에서 어떻게 작동하는지 모름. 테스트해보려고 하였으나, 이미 경고받아서인지 실행 2번만에 경고팝업
- 해당 코드를 7/20부터 돌려서 사용예정 (스케쥴링 적용 - 하루 3번) => 06시, 12시, 18시 (어차피 시작시간도 랜덤딜레이여서 정각으로 걸어도 됨)
[추가 개선포인트]
- 어느정도 돌리면 해시태그를 바꾸어서 또 누르고 (랜덤하게)
=> 정말 불규칙하게 가는 것인데, 1시간 넘게 이전 코딩 개선하느라 머리가 잘 안돌아감
[인사이트]
- 알고리즘도 결국 정형화되고, 경험을 쌓아서 이런 패턴이면 봇이겠구나 라는 것을 깨닫는 구조이다.
그렇기 때문에 나조차 패턴이 전혀 예측이 안되는 코딩을 하면되지않을까.
=> 패턴 = 랜덤 * 랜덤 * 랜덤 * .....
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
import inspect, os, platform, time, random
def bot():
#좋아요 갯수 랜덤 정의
rand_cnt = random.randrange(182, 297)
print("이번 좋아요 작업의 총 피드 갯수는 {}개입니다".format(rand_cnt))
rand_tag = ['운동하는직장인','운동하는남자','운동하는여자','운동인증','운동일기','운동일지','눈바디','피트니스','직장인스타그램','운동스타그램','홈트','홈트레이닝']
#필요한 변수 정의
insta_id = '블라블라'
insta_pw = '블라블라'
insta_tag = random.choice(rand_tag) # 해시태그 하나 선택
print("작업할 해시태그는 '{}'입니다.".format(insta_tag))
insta_cnt = rand_cnt
insta_sort = 1
#크롬드라이버 로딩
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)
### 인스타그램 자동 좋아요 작업 ###
#
# 0. 좋아죠 시작작업 랜덤 적용
random_wait_time = random.randrange(3, 5)
print("좋아요 작업은 {}초 후에 시작됩니다".format(random_wait_time))
# 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)
# add. 로그인정보 저장 > '나중에 하기' 버튼 클릭
later_btn = driver.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/div/div/button')
later_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)
print("좋아요 작업 시작합니다")
# 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초 이상을 설정해주세요.
rand_time = random.randrange(24,58)
time.sleep(rand_time)
print(rand_time) # 랜덤 시간 주기 24~58s
# 7. 좋아요 작업 - 다음 피드로 이동
if idx < insta_cnt:
try:
i = 0
while i != 2:
i = random.randint(1,3)
next_feed = driver.find_element_by_link_text('다음')
next_feed.click()
time.sleep(1) # '다음' 클릭 딜레이 간격
except NoSuchElementException as n:
print('피드 개수 부족으로 작업이 종료됩니다.')
break
print('계획된 {} 좋아요 작업이 모두 완료되었습니다'.format(insta_cnt))
driver.quit()
bot()
스케쥴링 내용은 각각 한글 태그, 영문태그인데, 한국인이 활동하는 06~24시는 한글태그, 그외에 영어를 사용하는 외국인 활동시간을 00~06시 타겟으로 진행하였다. 횟수는 파이썬 코드에 하드코딩되어 있다. 매번 내가 입력할수도 있지만, 그렇다면 자동화가 아니기에 미리 계산해서 넣었다.
동시에 작업하면 더 좋지 않은가, 시간 간격을 20초 이내로 하면 더 빠르지 않겠냐는 의문이 생길순 있겠지만,
인스타그램에 불법으로 걸리지 않게끔 하기 위해서 조정하였다.
어제 20~30개 좋아요 수준이었던 내 최신 게시글이 왠지 모르게 중간에 파이썬이 멈추기는 하였지만,