見出し画像

【コード公開】Pythonで2ちゃんねるのまとめ作成を自動化するコードを書いてみた ~まとめくす編~

1.はじめに

これまで時間をかけて人間の手でやっていた作業の手間を最小限にできないか、願わくば副業として収益を得られないかということで、Pythonを勉強して様々な作業の自動化を図っています。

いくつかのシステムを構想しており、その一つとして2ちゃんねる(5ちゃんねる)のまとめ記事を自動で作成してWordPressに投稿するコードを書いたので、紹介します。

※なお、システムが動作することは検証済みですが、私自身はプロフェッショナルなプログラマーではなく、趣味でコードを書いている程度ですので、コードが決して美しくないという点についてはご了承ください。

2.本システムでできること

本システムでは、「まとめくす」というサイトを活用します。

まとめくすは、まとめブログ記事を簡単に作成できる【無料ツール】で、多くのまとめサイトの作成において使われているようです。
5ちゃんねる(5ch)・おーぷん2ちゃんねる(open2ch)・2ちゃんねる(2ch)互換掲示板に対応しています。

まとめくすへのログイン

コードを実行すると、最初にまとめくすにログインを行います。

まとめくすはログインをしなくても使用することができますが、今回のシステムではWordPressへの投稿までを実現しており、そのためにはログインは必須となります。

まとめくすの新規登録は非常に簡単なので、ここでは説明は割愛しますが、登録は事前に完了させておいてください。

スレッドの検索

まとめくすは、まとめ記事の作成だけでなく、スレッドタイトルから記事を検索する機能を持っています。

対象は、5ch.netとopen2ch.netです。

スレッド検索時における本システムの大まかな機能は以下のとおりです。

  • キーワードリストをテキストファイルから読み込み(複数キーワードの指定可能)

  • 読み込んだキーワードで記事を検索

  • 検索結果(最大50件)から、記事のURLを取得

  • 取得したURLをテキストファイルに保存

なお、まとめの対象とする記事(URLを取得する記事)の条件を、以下のように設定できます。

  • 最低レス数

  • 最大レス数

  • タイトルがNGワードを含む場合は除外(NGワードは事前に設定可能)

  • ニュー速(嫌儲)を除外(ニュー速(嫌儲)はまとめることが禁じられています)

  • すでにまとめた記事を除外

まとめ記事の作成

まとめ記事作成時における本システムの大まかな機能は以下のとおりです。

  • まとめ対象とする記事のURLを読み込み(上述のテキストファイルからの読み込み)

  • 採用するレス数を総レス数の何割にするかを設定(全てあるいはほとんどのレスを採用してしまうと、まとめではなくコピーとみなされてしまう可能性があります)

  • 採用するレスを選択

  • 採用するレスが画像を含む場合、その画像を取り込み

  • 採用するレスをランダムで装飾(文字の色や大きさの変更)

  • WordPressに投稿

なお、採用するレスの条件を、以下のように設定するようにしています。

  • レスがNGワードを含む場合は除外(NGワードは事前に設定可能)

  • レスアンカーを含むレスが「グロ」「死ね」を含む場合、アンカー元のレスも含めて不採用

  • アンカー元のレスが採用されなかった場合、そのレスに対するレスアンカーを含むレスも不採用

上述のように、採用するレス数に上限を設けておりますが(総レス数の○割)、最終的に採用するレスを選択するロジックは以下のとおりです。

  • 採用するレスの条件(NGワードに該当するなど)によって不採用となるレスが多く、採用可能なレス数が上限を下回った場合:全ての採用可能なレスを採用する

  • 採用可能なレス数が上限を上回った場合:上限を下回るようにランダムでレスを不採用とする

  • ただし、不採用とするレスをランダムで抽出する際に、最初のレス、画像を含むレス、100文字未満のレス、アンカー元のレスおよびそのレスアンカーを含むレスは、それ以外のレスよりも採用の優先度が高くなります。

3.デモ映像

  • ログイン・スレッド検索

  • まとめ作成

4.コードの説明

第5章に作成したコードを記載しています。ただし、一部事前設定が必要な箇所があり、また、カスタマイズしたい方もいらっしゃると思いますので、こちらでコードについて詳しく説明します。

ライブラリのインポート

1~8行目で、必要なライブラリをインポートしています。Seleniumをインストールしていない場合は、インストールしておいてください

まとめくすへのログイン

10~39行目は、まとめくすにログインするためのコードです。

まとめくすのアカウント情報を入力してください。24行目と26行目に、それぞれメールアドレスとパスワードを入力してください。

また、11~16行目のように、ところどころでテキストファイルにログを吐き出すように設定しています。エラーなどがあった場合は、ログを確認してみてください。

tdatetime = dt.now()
dt_now = tdatetime.strftime('%Y/%m/%d %H:%M:%S')
f = open('log.txt', 'a')
f.write(dt_now + ":まとめくすにアクセスしました\n")
f.close()

スレッドの検索

41~115行目は、スレッドを検索して、まとめ対象とする記事のURLを取得・保存するためのコードです。

以下のコード(43行目)の【comment_count=】の後の数字は、記事のレス数が記載した数字以上のものを検索するという意味です。
設定できる数字は、「1、5、10、20、30、40、50、60、70、80、90、100」ですが、レス数が少なすぎるとまとめ記事にしづらいので、私は50に設定しています。

search_url = 'https://2mtmex.com/search?q=' + item_search + '&comment_count=50'

以下のコード(47行目)では、NGワードを設定できます。ここで設定したワードをタイトルに含む記事は、まとめ対象から除外されます。
デフォルトでは、「嫌儲」と「part」をNGワードとして設定してます。

ng_title_list = ['嫌儲', 'part']

以下のコード(64行目)では、まとめ対象とする記事の最大レス数を設定しています。
まとめ記事を作成する際に採用するレス数は、40~100レス程度と言われているので、私は上記の設定とあわせて、50以上120以下のレス数となっている記事をまとめ対象にすることにしています。

if i_res_count <= 120 and board != 'ニュー速(嫌儲)' and ng_title == 0:

以下のコード(69~76行目)は、抽出したスレッドがすでにまとめ済みかどうかを確認するものです。一度まとめ対象とした記事はテキストファイルにURLを保存するようにしていますが、それを読み込んで重複を確認するようにしています。
なお、まとめ済みの記事が膨大になっていくとループも大変になるため、重複確認をするURLの最大数を設定しています。デフォルトでは最新の300個を確認対象にしていますが、変更する場合は以下のコードで300と書いてある2箇所を任意の同じ数字に変更してください。

with open('url_done.txt', 'r') as f:
    url_done_list = f.read().split('\n')
    url_done_list.remove('')

if len(url_done_list) > 300:
    check_list = len(url_done_list) - 300
else:
    check_list = 0

まとめ記事の作成

117~447行目は、まとめ記事を自動で作成してWordPressに投稿するためのコードです。

以下のコード(137~139行目)によって、WordPressに投稿するためのAPI設定を行います。
なお、複数のAPI設定を行っている場合、【select.select_by_value('1')】の数字を2や3に変更する必要があるかもしれませんので、その場合は適宜数字を変更してください。

API設定は事前に行っておいてください。以下のサイトが参考になります。うまくいかない場合は、「エラー発生時の対処方法」も確認し、確実に設定しておいてください。

dropdown_api = driver.find_element_by_id('registered_api')
select = Select(dropdown_api)
select.select_by_value('1')

以下のコード(155行目)は、最終的なレス数調整用の数字です。
全てあるいはほとんどのレスを採用してしまうと、まとめではなくコピーとみなされてしまう可能性がありますので、採用するレス数を総レス数の何割にするかを設定しています。デフォルトでは0.9(9割)としていますが、お好みに合わせて変更してみてください。

res_del = 0.9 #採用するレス数を総レス数の何割にするか

以下のコード(374~418行目)では、採用するレスの加工をしています。

「# 太字化」以下の3行によって、全ての採用レスを太字にします。

1つ目の「# サイズ変更」以下の3行によって、全ての採用レスのサイズを3にします。
文字サイズは1~7まで用意されていますので、変更したい場合は、【select.select_by_value('2')】の数字部分を0~6にしてください(設定したい文字サイズから-1した数字を入力してください)。

【if num_deco == 0:】以下のコードで、1番目のレスの色を青字(value=5)に設定します。
色を変更したい場合は、下記を参考にしてください。

【elif num_deco == num_last_res:】以下のコードで、選択した最後のレスの色をピンク(value=0)かつ大文字(文字サイズ4)に変更します。

【elif res_len50[num_deco] == False and random_deco < 0.25:】以下のコードによって、50文字未満のレスのうちの25%をランダムで加工します。
50文字未満の条件をなくしたい場合は、【res_len50[num_deco] == False and 】を削除してください。加工する割合を変更したい場合は、【random_deco < 0.25】の数字部分を0~1の間で設定してください(0=0%で1=100%となります)。
デフォルトでは、加工する25%のうち、紫 15%、橙 15%、緑 30%、青 10%、赤 30%になるようにしています。この割合や色を変更する場合は、if文(elif文)に記載している数字や【value=】の数字を変更してください。
さらに、色づけしたレスのうちの30%を大文字(文字サイズ4)にします。

※色の変更:ピンク(value=0)、紫(value=1)、茶色(value=2)、橙(value=3)、緑(value=4)、青(value=5)、濃い赤(value=6)、赤(value=7)、薄い茶色(value=8)、オリーブ(value=9)
※文字サイズの変更:文字サイズ1(value=0)、文字サイズ2(value=1)、文字サイズ3(value=2)、文字サイズ4(value=3)、文字サイズ5(value=4)、文字サイズ6(value=5)、文字サイズ7(value=6)

if num_choice >= 5:
    for num_deco in range(i_res_count):
        if res_choice[num_deco] == True:
            random_deco = random.random()
            # 太字化
            num_bold = num_deco * 4
            check = driver.find_elements_by_css_selector("input[type='checkbox'][class=tool_deco]")[num_bold]
            driver.execute_script('arguments[0].click();', check)
            # サイズ変更
            dropdown = driver.find_elements_by_class_name('tool_size')[num_deco]
            select = Select(dropdown)
            select.select_by_value('2')
            if num_deco == 0:
                # 色づけ
                driver.find_elements_by_css_selector("input[type='radio'][value='5']")[num_deco].click()
            elif num_deco == num_last_res:
                # 色づけ
                driver.find_elements_by_css_selector("input[type='radio'][value='0']")[num_deco].click()
                # サイズ変更
                dropdown = driver.find_elements_by_class_name('tool_size')[num_deco]
                select = Select(dropdown)
                select.select_by_value('3')
            elif res_len50[num_deco] == False and random_deco < 0.25: #50文字未満かつ25%を加工
                # 色づけ
                random_deco1 = random.random()
                if random_deco1 < 0.15:
                    driver.find_elements_by_css_selector("input[type='radio'][value='1']")[num_deco].click() #紫 15%
                elif random_deco1 < 0.3:
                    driver.find_elements_by_css_selector("input[type='radio'][value='3']")[num_deco].click() #橙 15%
                elif random_deco1 < 0.6:
                    driver.find_elements_by_css_selector("input[type='radio'][value='4']")[num_deco].click() #緑 30%
                elif random_deco1 < 0.7:
                    driver.find_elements_by_css_selector("input[type='radio'][value='5']")[num_deco].click() #青 10%
                else:
                    driver.find_elements_by_css_selector("input[type='radio'][value='7']")[num_deco].click() #赤 30%
                # サイズ変更
                random_deco2 = random.random()
                if random_deco2 < 0.3:
                    dropdown = driver.find_elements_by_class_name('tool_size')[num_deco]
                    select = Select(dropdown)
                    select.select_by_value('3') #大文字 30%
            else:
                # チェック
                check = driver.find_elements_by_css_selector("input[type='checkbox'][class=selects]")[num_deco]
                driver.execute_script('arguments[0].click();', check)

if name == 'main':の中身

449~500行目のコードについてです。

以下のコード(450~457行目)では、Seleniumを利用する際の各種設定を行います。

SeleniumとChromeDriverのインストールが必要になりますので、以下のサイトを参考に必要な設定を完了させてください。
以下の設定だけ行えば問題ありません(括弧内は参考URL内の見出し)。

  • Seleniumのインストール(「環境」)

  • ChromeDriverのインストール(「バイナリを直接ダウンロードする場合」または「pipでインストールする場合」)

  • 【driver = webdriver.Chrome(executable_path='Chromeドライバーのパスを入力 + /chromedriver.exe', options=options)】部分へのパスの設定(「プログラムでのパス指定」)

最後に、【profile_path =】部分にChromeのプロファイルパスを入力してください。こちらの設定は、以下のサイトが参考になります。

なお、【options.headless = True】はコメントアウトしております。このコメントアウトを外すと、Chromeのウインドウが開かずにバックグラウンドでプログラムが走るため、動作確認がしっかりできるまではコメントアウトしたままにしておくことをオススメします。

options = webdriver.chrome.options.Options()
profile_path = 'Chromeのプロファイルパスを入力'
options.add_argument('--user-data-dir=' + profile_path)
# ブラウザを非表示
# options.headless = True

driver = webdriver.Chrome(executable_path='Chromeドライバーのパスを入力 + /chromedriver.exe', options=options)
driver.implicitly_wait(10)

以下のコード(460行目)は、「まとめくすへのログイン」を実行するコードです。

login()

以下のコード(463~465行目)では、スレッドを検索する際のキーワードを読み込みます。pyファイルと同じフォルダに、「keyword.txt」というテキストファイルを作成し、キーワードを入力しておいてください。複数のキーワードを設定したい場合は、改行してそれぞれの行に検索したいキーワードを入力するようにしてください。

with open('keyword.txt', 'r') as f:
    search_list = f.read().split('\n')
    search_list.remove('')

以下のコード(468~469行目)は、「スレッドの検索」を実行するコードです。
キーワードを複数設定している場合、そのキーワードの分だけループして実行します。

for item_search in search_list:
    search()

以下のコード(477~479行目)は、NGワードを読み込みます。「ng_words.txt」を作成しておいてください。上述の検索キーワードと同様に、改行によってNGワードを複数設定可能です。

with open('ng_words.txt', 'r') as f:
    ng_word_list = f.read().split('\n')
    ng_word_list.remove('')

以下のコード(483~484行目)は、「まとめ記事の作成」を実行するコードです。
「スレッドの検索」で複数のURLが抽出されている場合、そのキーワードの分だけループして実行します。

for url in read_url_list:
    matome()

説明を省略しているところもありますが、それらは基本的には変更する必要がない部分となります。

ここから先は

19,937字

¥ 7,800

期間限定 PayPay支払いすると抽選でお得に!

この記事が気に入ったらサポートをしてみませんか?