あぼぼーぼ・ぼーぼぼ

のんびり生きたい

PythonでTwitter自動投稿botをつくるときに調べたもの

ウェブサイトを定期的にスクレイピングし、自然言語処理をしてその結果をもとにTwitterに投稿するbotをつくった。その際に必要だった技術、調べたもののメモ。

クローラー

scrapy

Pythonクローラーがつくれるフレームワーク。大変お世話になりました。

scrapy-doc-ja.readthedocs.io

qiita.com

今回でいうと自然言語処理をするパイプラインとTwitterに投稿するパイプラインの2つを実装した感じ。

cssセレクタ一覧

scrapy-doc-ja.readthedocs.io

相対パス絶対パスに変換

import scrapy

class MySpider(scrapy.Spider):
    def parse(self, response):
        relative = response.css('a::attr(href)').extract_first()
        absolute = response.urljoin(relative)

ref https://docs.scrapy.org/en/latest/topics/request-response.html#scrapy.http.Response.urljoin

scrapyのロギング最低レベル変更

settings.pyに追記

LOG_LEVEL = "INFO"

ref https://doc-ja-scrapy.readthedocs.io/ja/latest/topics/settings.html#std:setting-LOG_LEVEL

Python言語系

文字列を○文字まで切り取る

# 'あいうえお'
five_str = 'あいうえおかきくけこ'[:5]

文字列をdatetimeに変換

import datetime

date_str = '2020.06.01 12:00'
date = datetime.datetime.strptime(date_str, '%Y.%m.%d %H:%M')

ref Pythonで文字列 <-> 日付(date, datetime) の変換 - Qiita

JST現在時刻をdatetimeで取得

import datetime

dt_jst = datetime.datetime.now(
    datetime.datetime.timezone(datetime.datetime.timedelta(hours=9))
)

ref Pythonで現在時刻・日付・日時を取得 | note.nkmk.me

datetimeの差を求める

タイムゾーンを考慮したdatetimeと、考慮していないdatetimeは計算できない。

import datetime

dt = datetime.datetime.now()
dt1_jst = datetime.datetime.now(
    datetime.datetime.timezone(datetime.timedelta(hours=9))
)
dt2_jst = datetime.datetime.now(
    datetime.datetime.timezone(datetime.timedelta(hours=9))
)


# TypeError: can't subtract offset-naive and offset-aware datetimes
diff = dt - dt1_jst

# OK
diff = dt1_jst - dt2_jst
# diffはtimedeltaオブジェクト
diff.total_seconds() # 0.0

ref python - Can't subtract offset-naive and offset-aware datetimes - Stack Overflow

ref datetime --- 基本的な日付型および時間型 — Python 3.8.3 ドキュメント

docstring

Googleが公開しているdocstringガイドか、numpyというのが主流らしい。

ref styleguide | Style guides for Google-originated open-source projects

ref numpydoc docstring guide — numpydoc v1.1.dev0 Manual

ref [Python]可読性を上げるための、docstringの書き方を学ぶ(NumPyスタイル) - Qiita

カレントディレクトリの絶対パスを取得

import os

path = os.getcwd()

ref os --- 雑多なオペレーティングシステムインタフェース — Python 3.8.3 ドキュメント

自然言語処理

janome.Tokeniserでユーザー辞書を使う

janomeは簡略辞書というフォーマットを使えたため、比較的簡単にユーザー辞書を追加することができました。

from janome.tokenizer import Tokenizer

# uidc.csvの中身の例↓
# あつ森,カスタム名詞,アツモリ
# とたけけ,カスタム名詞,トタケケ
t = Tokenizer(
    udic='udic.csv',
    udic_type='simpledic'
)
t.tokenize(text)

ref Welcome to janome's documentation! (Japanese) — Janome v0.3 documentation (ja)

特定品詞のみ抽出

from janome.tokenizer import Tokenizer

for token in t.tokenize(text):
    if (token.part_of_speech.startswith('名詞,固有名詞')
        or token.part_of_speech.startswith('名詞,一般')
        or token.part_of_speech.startswith('形容詞,自立')
        or token.part_of_speech.startswith('カスタム名詞')):
            print(token.surface)

Twitter API

Twitter API 利用申請手順

全て英語で書かなければならず、さらに○○文字以上の制約がある項目もあり少々面倒。DeepL翻訳にお世話になりました。

www.deepl.com

ref 2020年度版 Twitter API利用申請の例文からAPIキーの取得まで詳しく解説 | 新宿のホームページ制作会社 ITTI(イッティ)

PythonTwitter APIクライアント

いろいろ見つかったが今回はこれを使用。

ref https://pypi.org/project/twitter/

Heroku連携系

秘匿情報をHerokuのConfig Varsから注入

Twitter APIの認証情報などはソースコードにベタ書きしたくないため、Herokuの機構をつかって環境変数にいれます。Pythonから環境変数を取得する方法は下記のとおり。

import os

os.environ.get('SECRET_VALUE', 'default value')

ref https://devcenter.heroku.com/articles/getting-started-with-python#define-config-vars

Heroku Schedulerで定期実行

Herokuのアドオンで追加できる。Dyno Sizeが無料だと10分ごと、○時間ごと、○日ごと、の3パターンが使える。

ref https://devcenter.heroku.com/articles/scheduler