반응형

안녕하세요, 왕초보 코린이를 위한 코딩유치원에 오신 것을 환영합니다.

 

<관련 글>

 

2021.05.20 - [파이썬 프로젝트] - 일론 머스크 트위터 실시간 크롤링을 통한 비트코인 매매 수익률 검증 (feat. Tesla has Diamond Hands)

2021.05.20 - [파이썬 프로젝트] - 일론 머스크 트위터 실시간 크롤링을 통한 도지코인 매매 수익률 검증 (feat. How much is that Doge in the window?)

 


 

오늘은 최근 코인 열풍의 가장 중심에 있는 테슬라의 CEO인 일론 머스크의 트위터를 실시간 크롤링해보았습니다.

 

이 프로젝트는 일론 머스크의 말 한마디에 비트코인과 도지코인의 가격이 급등락하는 비이성적인 상황을 이용해서 코인 투자를 해보면 어떨까라는 생각에서 시작하였습니다.

 

이 프로젝트의 목적은 다음과 같습니다.

 

"일론 머스크 트위터를 실시간으로 감시하여, 새로운 트윗에 올라 왔을 때 텔레그램 봇을 이용해서 나에게 알려준다"

 

근 시일 내로 네이버 클라우드 플랫폼을 이용해서, 오늘 만든 코드를 계속 실행시켜줄 나만의 서버를 만들고,  텔래그램 채널을 만들어서 다른 사람들도 이용할 수 있는 서비스로 만들 계획입니다.

 


 

<2021년 5월 16일 글 수정>

 

이 글을 작성한 다음날 우연히 제가 생각하던 서비스를 이미 텔래그램 채널로 구현해놓은 것을 발견하여 공유하고자 합니다.

 

먼저 텔레그램 앱을 휴대폰에 설치하신 후, 아래와 같이 elon musk twitter 채널을 검색해 줍니다.

 

 

위의 채널을 클릭하고 들어가서 화면 화단의 알림켜기를 눌러주시면 실시간으로 일론 머스크 관련 트위터를 받아 보실 수 있습니다.

참고로, Elon Musk 개인 트위터 뿐만 아니라 SpaceX의 트위터도 실시간으로 알려주는 것으로 파악됩니다.

 

 


 

<혼자 진행했던 파이썬 프로젝트 코드>

 

오늘은 일단 컴퓨터에서 파이썬 코드가 돌아갈 때, 제 개인 텔레그램 봇을 이용해 메시지를 보내는 것 까지 해보았습니다.

 

전공자가 아니라서 코드가 매우 지저분 할 수 있다는 점 양해바랍니다.

 

#step1.라이브러리 불러오기

#웹 크롤링을 위한 패키지
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

#사용자에게 메시지 전송을 위한 패키지
import telegram

#주기적으로 프로그램을 작동시키기 위한 패키지
from apscheduler.schedulers.blocking import BlockingScheduler

#step2.텔레그램 봇 불러오기

#토큰을 변수에 저장
bot_token = '자신의 텔레그램 봇 토큰 입력'

#telegram 패키지의 Bot 함수를 사용하여 내가 만든 bot 사용
bot = telegram.Bot(token = bot_token)

#bot과의 채팅 정보 및 메세지 업데이트
#예전(불과 어제)의 정보를 못 불러오는 것으로 파악됨. 프로그램 시작 전에 bot에게 아무 메시지나 보내주어야함

#가장 최근에 온 메세지의 정보 중, chat id만 가져옴 (이 chat id는 사용자(나)의 계정 id임)
chat_id = bot.getUpdates()[-1].message.chat.id

#위에서 얻은 chat id로 bot이 메세지를 보냄.
bot.sendMessage(chat_id = chat_id, text="Elon Musk의 트위터 실시간 크롤링이 시작 되었습니다") 


#step3.주기적으로 명령을 실행할 스케쥴러 생성
sched = BlockingScheduler()

#step4.기존에 보냈던 메시지를 담아둘 리스트 만들기
old_contents = []

#step5.트위터 메시지 크롤링 함수 만들기 (매개변수는 이전에 수집해둔 메시지가 담긴 리스트)
def get_content(old_contents=[]):

	#크롬드라이버로 일론 머스크 트위터 접속
    url = 'https://twitter.com/elonmusk'
    driver = webdriver.Chrome('크롬 드라이버의 디렉토리(경로) 입력')
    driver.get(url)
    time.sleep(3)

    contents = []

    for i in range(10):
        
        try:
            twitter = driver.find_element_by_xpath(f'//*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[{i}]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span')
            contents.append(twitter.text)

        except:
            pass
   
    time.sleep(3)

    new_contents=[]

    for content in contents:
        if content not in old_contents:
            new_contents.append(content)
    
    return new_contents

#step6.텔레그램 메시지 전송 함수 만들기
def send_contents():
    global old_contents
    new_contents = get_content(old_contents)

    if new_contents:
        for content in new_contents:
            bot.sendMessage(chat_id=chat_id, text=content)
    else:
        # pass
        bot.sendMessage(chat_id=chat_id, text='새로운 트윗 없음')
        # else일 때 아무것도 안보내고 싶으면 그냥 pass로 바꾸면 됨. 실제 사용 때는 pass로 할 것

    old_contents += new_contents.copy()
    # old_contents = list(set(old_contents))

#step7.최초 시작, 스케쥴러 세팅 및 작동
send_contents()

# hours는 시, minutes는 분, seconds는 초
sched.add_job(send_contents, 'interval', seconds=10)

sched.start()

 

<새로 배운 점>

 

1. 정적 크롤링 방식으로는 twitter에서 막아둔 것인지 크롤링이 되지 않음  --> 실제 사용자가 클릭하 듯 동적 크롤링 방식 이용

 

2. css selector로 선택하기 어려운(아직 내가 잘 몰라서) 부분을 xpath의 규칙을 이용해 선택해서 크롤링 함

 

사용한 코드

for i in range(10):
        
        try:
            twitter = driver.find_element_by_xpath(f'//*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[{i}]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span')
            contents.append(twitter.text)

        except:
            pass

 

일론 머스크 트위터의 4, 5, 6번째 메시지의 xpath

 

# //*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[4]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span

 

# //*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[5]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span

 

# //*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[6]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span

 

 

<해결 못 한 점>

 

send_contents 함수에서 실행되는 get_contents가 실행될 때 마다 크롬 창이 떠서 불편함

 

#크롬 드라이버 실행 시 (창 뜨지 않는 옵션 추가)

 

options = webdriver.ChromeOptions()

options.add_argument("headless")

options.add_argument("--disable-gpu")

options.add_argument("lang=ko_KR")



driver = webdriver.Chrome('크롬 드라이버 경로', chrome_options=options)

 

 

 

반응형

+ Recent posts