친구의 실험/연구 참여를 돕기 위해 에브리타임 홍보게시판 스크래핑을 진행하게 되었다. 홍보게시판 스크래핑을 통해 실험 관련 새 글이 올라오면 메시지를 보내주는 봇을 만들었다. 그런데 왜 에브리타임 크롤링이라고 적지 않았을까? 크롤링과 스크래핑의 차이에 대해 알아둘 필요가 있다.
Web crawling, also known as Indexing is used to index the information on the page using bots also known as crawlers.
Web scraping is an automated way of extracting specific data sets using bots which are also known as ‘scrapers’.
웹사이트에서 특정 데이터를 추출하여 사용하였기 때문에 이번 프로젝트는 웹 크롤링보다는 웹 스크래핑이 더 적합하다고 생각한다.
Robots.txt
웹 스크래핑에 있어서 중요한 것은 무엇보다도 스크래핑하려는 웹사이트가 어떤 페이지의 스크래핑을 허용하는지 파악하는 것이다. 그럼 이를 어떻게 알 수 있을까? 바로 웹사이트의 최상위 경로(루트)로 가서 robots.txt를 넣으면 볼 수 있다. ex) https://everytime.kr/robots.txt
에브리타임의 robots.txt를 확인해보자.
User-agent: *
Allow: /$
Disallow: /
에브리타임은 모든 문서에 대해 접근을 차단하고, 첫 페이지에 대해서만 접근을 허용한다. 홍보게시판 최신 글들이 에브리타임 첫 페이지에 있으므로 문제없이 스크래핑을 진행할 수 있다. 파이썬을 이용해서 어떻게 스크래핑을 할 수 있을까?
에브리타임 로그인
로컬 환경에서 Selenium을 이용해 에브리타임 홈페이지를 띄우고 로그인하는 과정은 아래의 블로그에서 자세히 설명하고 있다.
하지만 Colab과 같은 클라우드 플랫폼에서는 크롬 창을 띄울 수 없으므로 위 블로그의 코드를 이용할 수 없다. webdriver에 headless 옵션을 추가하고 user-agent 값을 수정해야 한다.
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
from selenium import webdriver
webdriver_options = webdriver.ChromeOptions()
webdriver_options.add_argument('--headless')
webdriver_options.add_argument('--no-sandbox')
webdriver_options.add_argument('--disable-dev-shm-usage')
webdriver_options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36')
driver = webdriver.Chrome('chromedriver', options=webdriver_options)
driver.implicitly_wait(1)
# 로그인 페이지에서 로그인하기
url = 'https://everytime.kr/login'
driver.get(url)
driver.find_element(By.NAME, 'userid').send_keys(id)
driver.find_element(By.NAME, 'password').send_keys(pw)
driver.find_element(By.XPATH, '//*[@id="container"]/form/p[3]/input').click()
driver.implicitly_wait(5)
user-agent 값을 수정하지 않으면 headless 속성이 user-agent 값으로 설정된다. user-agent 값을 수정하지 않아도 스크래핑을 할 수 있는 웹 사이트도 있지만 에브리타임은 NoSuchElementException: Unable to locate element 에러가 발생하면서 스크래핑을 할 수 없다. 크롬 headless 모드 접근을 막아놨기 때문이다.
크롬 user-agent 값 확인
- F12 > Console > navigator.userAgent
홍보게시판 스크래핑
Selenium webdriver의 find_element를 통해 에브리타임 첫 페이지에 보이는 홍보게시판 최신 게시물들을 스크래핑하였다. xpath 대신 id, name, css_selector 등을 이용할 수 있으므로 자세한 사용법을 알고 싶다면 Selenium 공식 사이트를 확인해보길 바란다.
title = driver.find_element(By.XPATH, f'//*[@id="container"]/div[4]/div[24]/div/a[{i}]/p')
최신 글 확인
홍보게시판에 실험 관련 새 글이 올라왔는지 어떻게 파악할 수 있을까? 다양한 방법이 있을 수 있겠지만 나는 다음과 같은 방법을 이용했다.
1. 홍보게시판을 확인하여 실험 관련 최신 게시물 5개의 제목을 텍스트 파일에 저장한다.(이 과정은 반복하지 않아도 된다.)
2. 홍보게시판의 최신 게시물 4개의 제목을 스크래핑하여 실험 관련 키워드[실험, 연구, 참가 등]가 포함되어 있는지 확인한다.
3. 실험 관련 키워드를 포함한 게시물이라면 텍스트 파일과 비교하여 최신 게시물인지 아닌지 파악하고 텍스트 파일에 저장되어 있지 않은 최신 게시물이라면 텍스트 파일을 업데이트한다.
isUpdated = False
for i in range(1, 5):
title = driver.find_element(By.XPATH, f'//*[@id="container"]/div[4]/div[24]/div/a[{i}]/p')
title = title.text
title = emoji.demojize(title)
hasKeyWord = False
for keyword in keyword_list:
if keyword in title:
hasKeyWord = True
break
if hasKeyWord and title not in title_list:
for j in range(4, 0, -1):
title_list[j] = title_list[j-1]
title_list[0] = title
isUpdated = True
텔레그램
최신 게시물을 저장하는 텍스트 파일이 업데이트되었으면 메시지를 보내주는 봇을 만들어보자. 페이스북, 카카오톡 등을 통해 봇을 만들 수도 있지만 쉽게 봇을 만들 수 있는 텔레그램을 이용하였다. 텔레그램 봇을 생성하고 token과 user_id를 확인하는 방법은 아래의 블로그에서 자세히 설명하고 있다.
봇의 token과 메시지를 받을 유저의 userId를 알면 단 2줄로 메시지를 보낼 수 있다.
bot = telegram.Bot(token=TOKEN)
bot.sendMessage(chat_id=USER_ID, text='에브리타임 새 글이 올라왔습니다!')
소스코드
전체 소스코드는 여기서 확인할 수 있다.
'데이터 엔지니어링' 카테고리의 다른 글
[Python] Selenium을 활용한 에브리타임 스크래핑(2) - GCP (0) | 2022.03.08 |
---|
댓글