셀레니움을 활용한 Chat GPT to Slack
셀레니움은 웹 브라우저를 컨트롤 하는 것을 도와주는 도구다.
이 말은 웹 브라우저를 활용한 서비스라면 거의 대부분 셀레니움이 브로커 역할을 하면서 서로 결합될 수 있는 것이다.
셀레니움을 사용하여 ChatGPT에 접속하려고 하면 CLOUDFLARE가 무한 루프를 돌기 시작한다.
봇에 의한 크롤링을 방지하기 위해서 일련의 기법들이 적용되어 있는 것이다.
기업에서 하지 말라고 하면 가급적 안하는게 좋다.
API를 제공하고 있으니 말이다... 그러나, 이번엔 학습을 목적으로 "셀레니움" 만을 사용하여 어떻게든 설계를 완성시키는게 목적이었다.
이에 따라서 원격 디버깅을 통해 Chat GPT는 미리 접속을 해놓는다.
터미널에서 해당 명령어 실행해서 크롬 원격 디버그창을 띄워놓은 상태에서 코드 실행
[windows]
start chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\temp"
[MacOS]
sudo /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
윈도우는 안해봐서 제대로 작동하는지 정확히 모른다.
만약 안된다면 크롬 원격 디버깅을 검색해서 창을 띄우면 된다. 별도로 창이 열려야 제대로 작동한다는 의미다.
구글에 Chat GPT를 검색하고 일반적인 방법과 동일하게 로그인도 하고 접속해서 창을 띄워놓으면 끝.
이후에는 아래의 코드를 실행시키면 된다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.chrome.options import Options
import time
your_email = "여러분의 이메일(사실 수동으로 해도 된다)"
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver2 = webdriver.Chrome(options=options)
driver.get("https://slack.com/signin#/signin")
driver2.get("https://chat.openai.com/")
driver2.implicitly_wait(10)
id_input = driver.find_element(By.ID, "signup_email")
actions = ActionChains(driver)
actions.send_keys_to_element(id_input, your_email).perform()
actions.send_keys(Keys.RETURN).perform()
input("Press Enter to continue...")
## Chat GPT의 경우에는 구글 로그인같은 내역을 남겨놔야 접속이 되므로 완전 자동화는 힘들다.
## 여기서 로그인 -> 채널 접속까지 한 뒤에 엔터키를 누른다.
slack_recent_message = ""
slack_to_gpt_input = ""
recent_answer = ""
while True:
chats = driver.find_elements(By.CLASS_NAME, "p-rich_text_section")
if chats[-1].text == slack_recent_message:
# 최근 메세지가 이전에 받았던 메세지와 동일할 경우 스킵
print("슬랙 메세지가 업데이트 되지 않았습니다.")
time.sleep(5)
continue
elif chats[-1].text in recent_answer:
# 자문 자답 방지용, 대화 내용이 최근 답변과 유사할 경우 스킵
print("슬랙 메세지가 업데이트 되지 않았습니다.")
time.sleep(5)
continue
slack_recent_message = chats[-1].text
gpt_input = driver2.find_element(By.XPATH, '//*[@id="__next"]/div[2]/div/main/div[2]/form/div/div[1]/textarea')
gpt_button = driver2.find_element(By.XPATH, '//*[@id="__next"]/div[2]/div/main/div[2]/form/div/div[1]/button')
actions_gpt = ActionChains(driver2)
actions_gpt.send_keys_to_element(gpt_input, slack_recent_message).perform()
actions_gpt.click(gpt_button).perform()
driver2.implicitly_wait(3)
main_divs = driver2.find_elements(By.XPATH, '//*[@id="__next"]/div[2]/div/main/div[1]/div/div/div/div')
answer_num = len(main_divs) - 1
delay_check = 0 #Chat GPT가 대답하는 과정이 길기 때문에 대답 하는 동안에는 체크하다가 대답이 끝나면 전송
recent_answer = driver2.find_element(By.XPATH, '//*[@id="__next"]/div[2]/div/main/div[1]/div/div/div/div[%s]/div/div[2]/div[1]/div/div' % answer_num).text
while delay_check <= 2:
time.sleep(0.5)
tmp_answer = driver2.find_element(By.XPATH, '//*[@id="__next"]/div[2]/div/main/div[1]/div/div/div/div[%s]/div/div[2]/div[1]/div/div' % answer_num).text
if recent_answer == tmp_answer:
delay_check += 1
else:
delay_check = 0
recent_answer = tmp_answer
slack_input = driver.find_element(By.XPATH, '/html/body/div[2]/div/div[1]/div[5]/div[2]/div/div[4]/div/div[2]/div/div/div/div[2]/div/div/div/div[2]/div/div[1]/p')
actions.send_keys_to_element(slack_input, recent_answer).perform()
actions.send_keys(Keys.RETURN).perform()
Press Enter to continue... 가 나왔을 때
엔터를 누르기 전 조건은
1. 원격디버깅 크롬을 켜고 ChatGPT에서 메세지를 보내기 전 단계까지 접속이 확인
2. ChatGPT 에서 개발자 도구를 열어서 화면을 축소시킨 버전으로 만듦
예시)
3. 새롭게 열린 셀레니움에 의해 오픈된 Slack 창이 열린 크롬에서 자신이 메세지를 받고, 보낼 채널까지 접속
반자동이라 어쩔 수가 없다.
더 나은 대안이 있다면 말해주시면 감사하겠습니다.
잘 작동하는 모습이다.