2018年末、はてなブックマークで便利だった外部サービス連携「Twitterからブックマークを追加」サービスが終了しました。Qiita投稿時にツイートするとはてなブックマークにもブックマーク追加してくれて良かったのに。。。悲しい。。。
はてなブックマークがIDコール廃止。外部サービス連携も順次終了 - Impress Watch
https://www.watch.impress.co.jp/docs/news/1150477.html
「Twitterからブックマークを追加」や「mixi連携」、「Evernote連携」、「Facebook連携」などの外部サービス連携も11月初旬に終了。また、毎日、指定の時刻にマイホットエントリーをメールで送信する「マイホットエントリーメール」、お気に入りフィードを「はてなメッセージ」で送信する「お気に入りレポート」も終了する。
終了してからは手動でブックマーク追加していたのですが、他にも気になったサイトがあったときにツイートするかブックマークするか無駄に悩んだりすることが増えてきて面倒になったので、連携する仕組みを実装してみました。
はてなブックマークAPIがつかえる
はてなブックマークにAPIがあるのか調べてみたらありました。下記記事でブックマーク追加するサンプルもあげてくれているので参考にしました。(感謝
はてなブックマークを #API で追加する #python スクリプトの例 - Qiita
https://qiita.com/YumaInaura/items/0641702719fef0260d8e
APIに関しては公式ドキュメントが参考になります。
はてなブックマーク ブックマーク API - Hatena Developer Center
http://developer.hatena.ne.jp/ja/documents/bookmark/apis/rest/bookmark#post_my_bookmark_parameter_comment
OAuth認証を利用するにはConsumer key
を取得する必要がありますので、下記ドキュメントを参考にします。
Consumer key を取得して OAuth 開発をはじめよう - Hatena Developer Center
http://developer.hatena.ne.jp/ja/documents/auth/apis/oauth/consumer
APIを利用して自分のアカウント情報にアクセスするにはOAuth認証でアクセストークンを取得する必要があります。
下記ライブラリでさくっと取得できそうでしたがエラー発生したため、公式にあるRuby実装サンプルを利用してアクセストークンを取得しました。
はてなブックマーク Web APIを手軽に使えるgemを作った - Qiita
https://qiita.com/t__nabe/items/7918b6c6232eb14c248e
```console:ダメだった(´・ω・`)
gem install hatena_bookmark_client_for_ruby
get_hatebu_access_token
/Library/Ruby/Gems/2.3.0/gems/oauth-0.5.4/lib/oauth/consumer.rb:197:in request': parameter_rejected (OAuth::Problem) from /Library/Ruby/Gems/2.3.0/gems/oauth-0.5.4/lib/oauth/consumer.rb:214:in
token_request'
from /Library/Ruby/Gems/2.3.0/gems/oauth-0.5.4/lib/oauth/consumer.rb:155:in get_request_token' from /Library/Ruby/Gems/2.3.0/gems/hatena_bookmark_client_for_ruby-0.1.3/exe/get_hatebu_access_token:27:in
'
from /usr/local/bin/get_hatebu_access_token:22:in load' from /usr/local/bin/get_hatebu_access_token:22:in
'
```console
> touch oauth_consumer.rb
# 公式の「サンプルコード Ruby版」をコピペ
# YOUR_CONSUMER_KEYとYOUR_CONSUMER_SECRETを書き換える
> gem install sinatra
> ruby oauth_consumer.rb
[2019-05-18 14:07:10] INFO WEBrick 1.3.1
[2019-05-18 14:07:10] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin18]
== Sinatra (v2.0.5) has taken the stage on 4567 for development with backup from WEBrick
[2019-05-18 14:07:11] INFO WEBrick::HTTPServer#start: pid=29898 port=4567
http://localhost:4567 にアクセスして、はてなブックマークでアクセスを許可してトークンを取得します。
Twitter APIを利用してツイートを取得する
Twitter APIの利用に関しては下記を参考にしました。
Pythonでサクッと簡単にTwitterAPIを叩いてみる - Qiita
https://qiita.com/ogrew/items/0b267f57b8aaa24f1b73
Twitter APIを利用するために必要となるアプリ登録とアクセストークン取得については以前に行ってたので今回はスキップします。下記が参考になります。
Twitter REST APIの使い方
https://syncer.jp/Web/API/Twitter/REST_API/
以前にもTwitter APIを利用したことがあり、ツイートを検索する際に、since:
とuntil:
を利用して期間指定できることを知ったので、それを利用して取得するツイートを絞り込みます。日時のフォーマットを2019-05-18_12:34:56_JST
と指定することで秒単位まで指定可能です。
Twitterの検索で時間を含む期間指定をする方法 - Qiita
https://qiita.com/kai_kou/items/336a9d1290c13abba7e2
ユーザーを指定するにはfrom:
が利用できるので、こんな感じのクエリで検索します。
Twitter検索:特定のユーザー、アカウント内を指定して検索する方法
https://appbu.jp/twitter-search-from-specific-user
from:k_aik_ou since:2019-05-18_12:34:56_JST until:2019-05-18_13:45:01_JST
Pythonで実装する
はてなブックマーク APIとTwitter APIが利用できることと必要となるキーが取得できたので、雑にPythonで実装します。consumerKey
、consumerSecret
、accessToken
、accessTokenSecret
は各自のに置き換えてください。
import json
import requests
from requests_oauthlib import OAuth1
from requests_oauthlib import OAuth1Session
import datetime,time,sys
import re
def tweet_to_hatebu():
# はてなブックマーク
hatena_auth = OAuth1(
"consumerKey",
"consumerSecret",
"accessToken",
"accessTokenSecret"
)
# Twitter
twitter_session = OAuth1Session(
"consumerKey",
"consumerSecret",
"accessToken",
"accessTokenSecret"
)
# APIのエンドポイント
bookmark_api_url = "http://api.b.hatena.ne.jp/1/my/bookmark"
twitter_api_url = "https://api.twitter.com/1.1/search/tweets.json"
# ツイート取得する期間を指定する
# from_atは定期実行する間隔に合わせて調整する
now = datetime.datetime.now()
from_at = now - datetime.timedelta(minutes=10)
from_at_str = from_at.strftime("%Y-%m-%d_%H:%M:%S_JST")
to_at_str = now.strftime("%Y-%m-%d_%H:%M:%S_JST")
# 取得件数は適当に指定(最大100ツイート)
params = {
"q": "from:ツイッターのユーザー名 since:" + from_at_str + "until:" + to_at_str,
"lang": "ja",
"result_type": "recent",
"count": 100,
}
# 指定した条件のツイートが取得できるまでAPIを叩く
statuses = []
while True:
res = twitter_session.get(twitter_api_url, params = params, verify=True)
res_text = json.loads(res.text)
if len(res_text["statuses"]) == 0:
break
# Twitter APIの利用制限を超えたらヤメ
if res.headers["X-Rate-Limit-Remaining"] == 0:
break
statuses.extend(res_text["statuses"])
next_max_id = res_text["statuses"][-1]["id"] - 1
params["max_id"] = next_max_id
# ツイート時間でソートするなど
statuses = sorted(statuses, key=lambda x: x["created_at"])
for tweet in statuses:
# 画像を含むツイートは無視
if "media" in tweet["entities"]:
print("media")
continue
# ながいつぶやきは無視
if tweet["truncated"]:
print("truncated")
continue
# ツイートテキストからURLを取得する
text = tweet["text"]
url_pattern = r"(https?)(:\/\/[-_\.!~*\"()a-zA-Z0-9;\/?:\@&=\+\$,%#]+)"
matchOB = re.search(url_pattern, text)
# URLを含めずにブックマークにコメントする
comment = re.sub(url_pattern, "", text)
# リツイートだったらコメントは無視
rt_matchOB = re.search(r"RT ", text)
if rt_matchOB:
comment = ""
# URLがあったらコメントを添えてブックマーク追加する
if matchOB:
bookmark_url = matchOB.group()
print(requests.post(bookmark_api_url + "?url=" + bookmark_url + "&comment=" + comment, auth= hatena_auth).content)
tweet_to_hatebu()
必要なライブラリをインストールして実行するとツイート取得してブックマーク追加することができます。
> pip install requests requests_oauthlib
> python main.py
AWS Lambdaを利用して定期実行させる
実装できましたがこのままだと手動でスクリプト実行しなきゃいけないので、AWS Lambdaに関数を登録して定期実行させます。
前提
- AWSアカウントがある
- AWS Lambda関数作成権限がある
実装の手直し
AWS Lambdaで実行できるように実装を手直しします。tweet_to_hatebu
メソッドの実装は変わらずです。
> mv main.py lambda_function.py
import json
import requests
from requests_oauthlib import OAuth1
from requests_oauthlib import OAuth1Session
import datetime,time,sys
import re
def lambda_handler(event, context):
tweet_to_hatebu()
return {
"statusCode": 200,
"body": json.dumps("Hello from Lambda!")
}
def tweet_to_hatebu():
(略)
ZIPにまとめてアップロードする
こちらを参考に必要となるライブラリと実装をZIPにまとめてアップロードしてAWS Lambda関数を作成します。
【Python】AWS Lambdaで外部モジュールを使用する - Qiita
https://qiita.com/SHASE03/items/16fd31d3698f207b42c9
> pip install requests requests_oauthlib -t ./
> zip -r tweet2hatebu.zip ./*
ZIPファイルアップロード後は、ブラウザ上でファイル編集できるようになります。
このままだとdatetime.datetime.now()
で日時を取得したときにUTC時間となるので関数の環境設定にTZ
変数を追加します。値はAsia/Tokyo
です。
AWS Lambdaのタイムゾーン変更 - Qiita
https://qiita.com/nullian/items/39ecf1f6d0194b72e8e6
Amazon CloudWatch Eventを利用して定期的に関数が実行するようにします。ルールはお好みで。
これで、定期的にツイートに含まれるURLをはてなブックマークにブックマーク追加する仕組みが出来上がりました。
やったぜ。
まとめ
調査から実装してAWS Lambdaで動かせるようにするまで2時間くらいでできました。
安定稼働させるには各APIの利用制限などを考慮した実装にする必要があるかと思いますが、個人で利用する分にはこれくらい雑な実装でも良いかなと思います。
参考
はてなブックマークがIDコール廃止。外部サービス連携も順次終了 - Impress Watch
https://www.watch.impress.co.jp/docs/news/1150477.html
はてなブックマークを #API で追加する #python スクリプトの例 - Qiita
https://qiita.com/YumaInaura/items/0641702719fef0260d8e
はてなブックマーク ブックマーク API - Hatena Developer Center
http://developer.hatena.ne.jp/ja/documents/bookmark/apis/rest/bookmark#post_my_bookmark_parameter_comment
Consumer key を取得して OAuth 開発をはじめよう - Hatena Developer Center
http://developer.hatena.ne.jp/ja/documents/auth/apis/oauth/consumer
はてなブックマーク Web APIを手軽に使えるgemを作った - Qiita
https://qiita.com/t__nabe/items/7918b6c6232eb14c248e
Pythonでサクッと簡単にTwitterAPIを叩いてみる - Qiita
https://qiita.com/ogrew/items/0b267f57b8aaa24f1b73
Twitter REST APIの使い方
https://syncer.jp/Web/API/Twitter/REST_API/
Twitterの検索で時間を含む期間指定をする方法 - Qiita
https://qiita.com/kai_kou/items/336a9d1290c13abba7e2
Twitter検索:特定のユーザー、アカウント内を指定して検索する方法
https://appbu.jp/twitter-search-from-specific-user
AWS Lambdaのタイムゾーン変更 - Qiita
https://qiita.com/nullian/items/39ecf1f6d0194b72e8e6