LoginSignup
1
4

More than 1 year has passed since last update.

【Python】BeautifulSoupで複数サイトをスクレイピングして更新通知をChatWorkで送信する

Posted at

PythonのBeautifulSoupを使って、
複数のサイト(の最新記事)をスクレイピングし、
更新があればChatWorkに通知を送信するシステムを作成しました。

備忘録のために書き留めておきます。

メインとなるスクレイピングのコード

まずは必要なライブラリやモジュールをインポートします。

config や chatwork への通知処理は後ほど別ファイルに書きます。

site_checker.py
# coding: UTF-8
import requests
from bs4 import BeautifulSoup
from my_config import my_config, update_recent_article
from chatwork_notification import chatwork_notify

 
サイト別に記事一覧を取得する関数を書きます。
スクレイピングしたいサイトごとに、最新記事のDOMを取得するように調整してください。

site_checker.py
def extract_articles(page_html, type):
    if type == "A":
        main = page_html.find("div", class_="inner-news")
        articles = main.find_all("li", class_="table-view-cell media")
    elif type == "B":
        articles = page_html.find("div", class_="comicIndex-rightBox")
    return articles

 
次に、取得した記事から、記事のURLを抽出する関数を書きます。

site_checker.py
def extract_article_url(article, type):
    domain = ""
    if type == "A":
        domain = "https://AAA.jp"
    elif type == "B":
        domain = "https://BBB.com"

    url = domain + article.get("href")
    return url

 
次に、取得した記事から、記事のタイトルを抽出する関数を書きます。

site_checker.py
def extract_article_title(page_html, article, type):
    page_title = ""
    if type == "A":
        title = html.find("div", class_="media-body").getText()
        title = title.replace("\n"," ")
    elif type == "B":
        title = html.find("span", class_="titleBox").getText()
    return title + " " + page_title

 
取得した記事から、更新された記事を抽出します。
更新前の最新の記事のindexはmy_config.iniで管理します。

site_checker.py
def extract_update_article(page_url, articles, recent_article, name, type):
    article_list = []
    first_article_num = ""
    # 逆順に取得していき、最新記事より1つ古い記事のurlを取得
    for article in articles:
        if article == 0:
            continue
        url = extract_article_url(article, type)
        # URLから記事番号を取得
        if type == "A":
            article_num = url.replace(page_url + "episode/", "").replace("/", "")
        elif type == "B":
            article_num = url.replace("https://BBB.com/viewer/?cid=", "")

        if recent_article == article_num:
            break

        title = extract_article_title(page_html, article, type)
        article_list.append([title, url])

        if first_article_num == "":
            first_article_num = article_num

    # my_configを更新
    if first_article_num != "":
        update_recent_article(name, first_article_num)

    return article_list

 
メインの処理を書きます。

site_checker.py
if __name__ == "__main__":
    # スクレイピングしたいサイト数だけ処理を繰り返す
    for i in range(1, 2):
        # my_configを取得
        name = "web_info_" + str(i)
        page_url = my_config[name]['url']
        page_type = my_config[name]['type']
        recent_article = my_config[name]['recent_article']

        # スクレイピングする
        res = requests.get(page_url)
        page_html = BeautifulSoup(res.text, 'html.parser')

        # 記事一覧を取得する
        articles = extract_articles(page_html, page_type)

        # 更新された記事を取得する
        article_list = extract_update_article(page_url, articles, recent_article, name, page_type)

        # 更新された記事があれば通知する
        if len(article_list) > 0:
            chatwork_notify(list_=article_list)

設定ファイルに書くコード

my_config.py に、
my_config.ini ファイルの読み取りと、
my_config.ini ファイルへの書き込み処理を書きます。

my_config.py
# coding: UTF-8
import configparser
import re

my_config = configparser.ConfigParser()
my_config.read('./my_config.ini')

# recent_articleの記事番号を更新する関数
def update_recent_article(name, article_num):
    with open('./my_config.ini', 'r') as f:
        lines = f.readlines()

    with open('./my_config.ini', 'w') as f:
        name_flag = False
        for line in lines:
            if re.match(r'(\[' + name + '\])', line):
                name_flag = True
            if re.match(r'(recent_article =)', line):
                if name_flag:
                    name_flag = False
                    f.write("recent_article = {}\n".format(article_num))
                    continue
            f.write(line)

次にスクレイピングサイトの情報を.iniファイルに書きます。

my_config.ini
# coding: UTF-8
[chatwork_info]
in_webhook_url = 1

# サイトA
[web_info_1]
type = A
url = https://AAA.jp/
recent_article = 1

# サイトB
[web_info_2]
type = B
url = https://BBB.jp/
recent_article = 1

スクレイピングするサイトを増やしたい場合は、
上記と同じ形式で増やしてください。

その際、web_info_◯ の番号が重複したりずれたりしないように注意してください。

チャットワークへの通知コード

chatwork_notification.py
# coding: UTF-8
import requests

APIKEY = '取得したAPIキーを入力'
ENDPOINT = 'https://api.chatwork.com/v2'
ROOMID = '通知したいルームのIDを入力'

post_message_url = '{}/rooms/{}/messages'.format(ENDPOINT, ROOMID)

def chatwork_notify(list_=None):
    headers = {'X-ChatWorkToken': APIKEY}

    text = ""
    for element in list_:
        if text != "":
            text += "\n"
        text += element[0] + "\n" + element[1]

    params = {'body': text, "self_unread": 1}
    requests.post(post_message_url, headers=headers, params=params)

APIKEYとROOMIDはチャットワークにログインして取得します。

chatwork_notify関数は、site_checker.py で使用するものです。
通知したい内容に応じて、文章(text)等を好きに変更してください。

1
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4