Python 구글 뉴스 데이터 크롤링(apscheduler, nohup) - 2
Language/Python

Python 구글 뉴스 데이터 크롤링(apscheduler, nohup) - 2

뉴비뉴 2023. 2. 14.

https://newbiecs.tistory.com/365

 

Python 구글 뉴스 데이터 크롤링(beautifulsoup4, slack) - 1

안녕하세요. 요즘 할 일들이 많아서 일주일에 한번 글 쓰기가 소홀해졌네요. 오늘의 미션은 1. '한국타이어' 뉴스를 크롤링하라 2. 크롤링은 '매일' 오전 11시에 하고 싶다. 다음 게시글에서 작성

newbiecs.tistory.com

tstation.crawler()

 안녕하세요.

전에 작성했던 글을 마무리 해보겠습니다.

 

이번에 사용할 건 Python apscheduler와 nohup 되겠습니다.

저도 nohup를 처음 사용하는데요. 간단히 알아보자면

'프로세스가 중단되지 않는 백그라운드 작업을 수행' 하는 용도로 사용된다고 하네요.

 

다음으로 apscheduler 은 파이썬의 스케쥴러 모듈입니다.

특정한 주기로 해당 기능을 사용하고자 할 때 사용합니다.

 

해야할 것은 백그라운드 작업으로 크롤링 코드를 동작시키고,

특정 시간에 (9,11,13시 0, 30분) 크롤링을 하여

데이터를 가져오는 것을 만들어보겠습니다.

 

시작해보겠습니다.

1. apscheduler 설치

pip install apscheduler

2. 특정 시간에 코드 실행

if __name__ == '__main__':
    sched = BackgroundScheduler(timezone="Asia/Seoul")
    sched.start()

    while True:
        # 매일 09시, 11시, 13시 0분 30분 한국타이어 뉴스 크롤링
        @sched.scheduled_job('cron', hour='9,11,13', minute='0,30', id='am')
        def crawler_tstation_news():
            slack_url = os.environ['SLACK_WEBHOOK']
            headers = {"Content-Type": "application/json"}
            data = {
                "attachments": [{
                    "color": "#36a64f",
                    "title": "🔔 한국타이어 🔔",
                    }]}

            requests.post(url=slack_url, headers=headers, data=json.dumps(data))

            tstation.crawler()

        time.sleep(1)

@sched.scheduled_job('cron', hour, minute)

본인이 코드가 돌아가는 시간대를 설정하면 됩니다.

위 코드에서 설정 된 data는 맨 처음 코드를 실행하기 전 slack 에 출력되는 값을 말 합니다.

 

더 완벽한 코드를 한번 짜 볼까요?

그러면 우리는 생각해야 될 게 하나 더 있습니다.

 

과연 한국타이어에 대한 뉴스만 가져오면 될까요?

아니죠, 주식을 하다보면 내가 구매한 여러 개의 주식정보가 필요합니다.

 

전에 작성했던 crawler 코드를 수정하겠습니다.

삼성전자 관련 뉴스를 가져오겠습니다.

3. 크롤링 코드 수정

작업했던 tstation.py 파일을 crawlers.py 로 변경하겠습니다.

class 이름도 `class Crawlers` 로 변경하겠습니다.

class Crawlers:
    def __init__(self):
        self.headers = {"Content-Type": "application/json"}
        self.slack_url = os.environ['SLACK_WEBHOOK']

        self.tstation = requests.get(url='https://news.google.com/search?q=%ED%95%9C%EA%B5%AD%ED%83%80%EC%9D%B4%EC%96%B4+when:1d&hl=ko&gl=KR&ceid=KR%3Ako')
        self.samsung = requests.get(url='https://news.google.com/search?q=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90%20when%3A1d&hl=ko&gl=KR&ceid=KR%3Ako')

    def crawler(self, target):
        if target == 'tstation':
            html = self.tstation
        elif target == 'samsung':
            html = self.samsung

        soup = BeautifulSoup(html.text, 'html.parser')
        bs = soup.select(
            "#yDmH0d > c-wiz > div > div.FVeGwb.CVnAc.Haq2Hf.bWfURe > div.ajwQHc.BL5WZb.RELBvb"
        )
        answers = bs[0].findAll('h3', class_='ipQwMb ekueJc RD0gLb')

        if not answers:
            no_data = {
                "attachments": [{
                    "color": "#36a64f",
                    "title": f":warning: {target} 뉴스 데이터가 존재 하지 않습니다. :warning:",
                }]}
            requests.post(url=self.slack_url, headers=self.headers, data=json.dumps(no_data))
        else:
            for answer in answers:
                data = {
                    "attachments": [{
                        "color": "#36a64f",
                        "title": answer.text,
                        "title_link": f"https://www.news.google.com/{answer.find('a').get('href')}"
                        }]
                    }
                requests.post(url=self.slack_url, headers=self.headers, data=json.dumps(data))

좋습니다.

 

우리는 슬랙이 연동 된 상태로 위와 같은 코드가 완성되었고,

만약 그게 아니라면 data 코드를 삭제하고,

answers 정보를 return 하면 됩니다.

5. 전체 코드

import json, time, requests, os

from bs4 import BeautifulSoup
from apscheduler.schedulers.background import BackgroundScheduler


class Crawlers:
    def __init__(self):
        self.headers = {"Content-Type": "application/json"}
        self.slack_url = os.environ['SLACK_WEBHOOK']

        self.tstation = requests.get(url='https://news.google.com/search?q=%ED%95%9C%EA%B5%AD%ED%83%80%EC%9D%B4%EC%96%B4+when:1d&hl=ko&gl=KR&ceid=KR%3Ako')
        self.samsung = requests.get(url='https://news.google.com/search?q=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90%20when%3A1d&hl=ko&gl=KR&ceid=KR%3Ako')

    def crawler(self, target):
        if target == 'tstation':
            html = self.tstation
        elif target == 'samsung':
            html = self.samsung

        soup = BeautifulSoup(html.text, 'html.parser')
        bs = soup.select(
            "#yDmH0d > c-wiz > div > div.FVeGwb.CVnAc.Haq2Hf.bWfURe > div.ajwQHc.BL5WZb.RELBvb"
        )
        answers = bs[0].findAll('h3', class_='ipQwMb ekueJc RD0gLb')

        if not answers:
            no_data = {
                "attachments": [{
                    "color": "#36a64f",
                    "title": f":warning: {target} 뉴스 데이터가 존재 하지 않습니다. :warning:",
                }]}
            requests.post(url=self.slack_url, headers=self.headers, data=json.dumps(no_data))
        else:
            for answer in answers:
                data = {
                    "attachments": [{
                        "color": "#36a64f",
                        "title": answer.text,
                        "title_link": f"https://www.news.google.com/{answer.find('a').get('href')}"
                        }]
                    }
                requests.post(url=self.slack_url, headers=self.headers, data=json.dumps(data))


if __name__ == '__main__':
    sched = BackgroundScheduler(timezone="Asia/Seoul")
    sched.start()

    while True:
        # 매일 09시, 11시, 13시 0분 30분 한국타이어 뉴스 크롤링
        @sched.scheduled_job('cron', hour='9,11,13', minute='0,30', id='am')
        def crawler_tstation_news():
            crawlers = Crawlers()

            slack_url = os.environ['SLACK_WEBHOOK']
            headers = {"Content-Type": "application/json"}
            data = {
                "attachments": [{
                    "color": "#36a64f",
                    "title": "🔔 한국타이어, 삼성전자 크롤링 🔔",
                    }]}

            requests.post(url=slack_url, headers=headers, data=json.dumps(data))

            crawlers.crawler('samsung')
            crawlers.crawler('tstation')

        time.sleep(1)

6. nohup 로 apscheduler 코드를 비동기로 동작시키기

nohup python3 crawlers.py & # background 실행
and
nohup poetry run python3 crawlers.py & # my case

동작시키게 되면 nohup.out 이라는 파일이 생성됩니다.

nohup 에서 오류가 발생한다면 여기에 내용이 작성됩니다.

 

제가 전에 사용하던 slack 계정이 피치못할 사정으로 없어지면서

오늘 작성한 코드는 정확히 동작할 지 애매합니다. slack 관련 확인은 하지 못하였고,

Python 내에서 데이터가 들어오는 것을 확인했습니다.

 

혹시나 문제가 있으시다면 댓글 남겨주시고,

조언이나 수정사항이 있으시면 남겨주시면 감사하겠습니다!

 

감사합니다!

 

https://github.com/2044smile/google-crawling-tstation/blob/main/crawlers.py

 

GitHub - 2044smile/google-crawling-tstation

Contribute to 2044smile/google-crawling-tstation development by creating an account on GitHub.

github.com

 

댓글

💲 추천 글