話題のSNS Bluesky
若者のX離れ…のせいかわかりませんが、新たなSNSのBlueskyが人気になっています。
PythonでのAPIの利用についてポストはこちらやこちらの記事が参考になったのですがポストの検索などその他の処理の記載がなかったのでご参考までに紹介します。
基本的には以下のドキュメント通りです。
※下の方はメソッド名が若干異なっているので注意です
用語について
- ハンドル名…Xなどで言うユーザ名で"~.bsky.social"などです。
- DID…アカウント固有のID。ハンドル名ではなく変えることのできない値で"did:~"で始まります。
- URI…投稿(ポスト)を識別するID。Xと違いこのIDには上記DIDが含まれるようです。
- CID…ポストのコンテンツハッシュ値。ポストの正当性を保証。 ※こちらから参照しました
以下でActorという場合はハンドル名とDIDどちらでも使えるときに利用します
インストール・ログイン・ポスト
pip install atproto
from atproto import Client
client = Client()
client.login("ハンドル名(*****.bsky.socialなど)", "パスワード")
post_text = "ポストテスト"
client.send_post(text=post_text)
プロフィール取得
get_profile(Actor)でアカウントのプロフィールを取得します→ドキュメント
profile = client.get_profile("sora-sakurai.bsky.social")
print(profile)
did='did:plc:nc45m3kcywjhyr4tgsbmea64' handle='sora-sakurai.bsky.social' associated=ProfileAssociated(chat=None, feedgens=0, labeler=False, lists=0, starter_packs=0, py_type='app.bsky.actor.defs#profileAssociated') avatar='https://cdn.bsky.app/img/avatar/plain/did:plc:nc45m3kcywjhyr4tgsbmea64/bafkreigfxce42hajzeutuziv6o4fogryn7rtrlxmlni2vgoinidqcdti44@jpeg' banner=None created_at='2024-02-06T16:17:56.807Z' description='ソラ(Sora)代表 ゲームデザイナー/ゲームディレクター \n『星のカービィ』『大乱闘スマッシュブラザーズ』など。 \nとりあえずアカウント作ってみました!' display_name='桜井 政博 / Masahiro Sakurai' followers_count=61309 follows_count=0 indexed_at='2024-02-09T12:25:28.465Z' joined_via_starter_pack=None labels=[] pinned_post=None posts_count=63 viewer=ViewerState(blocked_by=False, blocking=None, blocking_by_list=None, followed_by=None, following=None, known_followers=None, muted=False, muted_by_list=None, py_type='app.bsky.actor.defs#viewerState') py_type='app.bsky.actor.defs#profileViewDetailed'
profile.display_nameなどでそれぞれの情報を取得できます。
アカウントのDIDを知りたい場合もprofile.didで取得して下さい。
(先述の通りActorなのでDIDからでも取得できます。)
※ちなみに自分のプロフィールはclient.me.XXXXXで取得できます。
フォロー・フォロワー取得
get_follows(Actor), get_followers(Actor)で対象のアカウントのフォロー・フォロワーを取得できます。→ドキュメント
res = client.get_follows("unicouniuni3.bsky.social")
for profile in res.follows:
print(profile.handle, profile.display_name)
kusagamegunso.bsky.social クサガメ軍曹(アメチカンのもな)
monamofumofu.bsky.social もなつむ
potene.bsky.social ぽてねのアポロとチロル兄さん
res = client.get_followers("unicouniuni3.bsky.social")
for profile in res.followers:
print(profile.handle, profile.display_name)
yorunosoko.bsky.social ヨノ底
randomcolor.bsky.social Lotus Nocturne
cozirase-ushio.bsky.social ジャーキー
ユーザ検索
app.bsky.actor.search_actorsでアカウントの検索ができます。→ドキュメント
actors = client.app.bsky.actor.search_actors({"q":"Vtuber", "limit":25})
for actor in actors.actors:
print(actor.handle, actor.display_name, actor.description)
akakura1341.bsky.social 赤倉🧸 イラストレーター🖋 甘いものとファッションとレトロが好きです
(…省略)
必須なのは検索ワードとなる"q"のみで最大件数などそれ以外は任意です。
これまでのメソッドと違い、引数を辞書型でセットします。
※client.app.bsky.XXXXX系のメソッドは引数を辞書型などで指定する必要があるようです
フォロー
follows(did)で対象のdidのアカウントをフォローします。→ドキュメント
これはハンドル名は利用できませんので、search_actorsなどでDIDを取得して下さい。
res = client.app.bsky.actor.search_actors({"q":"Vtuber", "limit":1})
for actor in res.actors:
client.follow(actor.did)
※一気にフォローしてしまうので注意してください
フォロー解除のunfollowも同様です。
ポスト検索
search_postsでポストの検索ができます。必須なのは検索ワードの"q"だけです。→ドキュメント
res = client.app.bsky.feed.search_posts({"q":"地震", "sort":"top", "limit":5})
for post in res.posts:
print(post.author.display_name, post.record.text)
ウェザーニュース 【海外地震情報】
日本時間の11月15日(金)14時29分頃、海外で地震がありました。
震源地はニューギニア付近(パプアニューギニア、ニューアイルランド)で、地震の規模はM6.7と推定されます。この地震による津波被害の心配はありません。
(…省略)
ソート(sort)は未指定なら最新順、"top"は見られている順になるかと思います。
対象のアカウントだけのポストを取得したい場合"author"にハンドル名をセットすればいいのですが、"q"が必須項目で面倒なので"q"に"from:(ハンドル名)"を指定した方が楽かと思います。
res = client.app.bsky.feed.search_posts({"q":"from:unicouniuni3.bsky.social"})
他にもアプリで使うように検索クエリが"q"にも利用できるかと思います。
いいね・リポスト
likeとrepostでいいね・リポストができます。ただXと違うのはポストのIDだけではなくCIDも必要になります。→ドキュメントいいね・リポスト
res = client.app.bsky.feed.search_posts({"q":"from:unicouniuni3.bsky.social", "limit":1})
for post in res.posts:
client.like(post.uri, post.cid)
client.repost(post.uri, post.cid)
こちらも一気に操作できてしまうので注意して下さい。
ちなみにURIが
"at://did:plc:5ysft3tkkncrn3xohxwqybxl/app.bsky.feed.post/3lba2gm3gys24"
だとして、ポストを表示するにはat://→https://bsky.app/profile/ にして"app.bsky.feed."を消して
https://bsky.app/profile/did:plc:5ysft3tkkncrn3xohxwqybxl/post/3lba2gm3gys24
ポストが表示できるようになります。(DIDをハンドルに変えても大丈夫です)
返信
返信は面倒です。send_postで返信先を指定するのですがReplyRefとやらにしなくてはいけません。→ドキュメント
①元ポストへの返信の場合(返信への返信でない)
res = client.app.bsky.feed.search_posts({"q":"from:nekoniiii.com", "limit":1})
uri=res.posts[0].uri
cid=res.posts[0].cid
from atproto import models
model = models.base.ModelBase(uri=uri, cid=cid)
parent = models.utils.create_strong_ref(model)
# parentとrootは同じ
root = parent
reply_ref=models.AppBskyFeedPost.ReplyRef(parent=parent, root=root)
create_record = client.send_post(text='返信',reply_to=reply_ref)
②返信への返信の場合(①の返信に返信します)
# ①の返信で得たuri・cidをセット
model = models.base.ModelBase(uri=create_record.uri, cid=create_record.cid)
parent = models.utils.create_strong_ref(model)
# rootは①と同じ
reply_ref=models.AppBskyFeedPost.ReplyRef(parent=parent, root=root)
create_record2 = client.send_post(text='返信への返信', reply_to=reply_ref)
ややこしいですがparentに返信するポスト、rootに元となるポストをセットします。こちらも参考にして下さい。
その他
ブロック一覧(自身がブロックしているアカウントです)
res = client.app.bsky.graph.get_blocks()
for profile in res.blocks:
print(profile.handle, profile.display_name)
matthewstadlen.bsky.social Matthew Stadlen
(…省略)
ポストへいいねしたアカウント一覧
res = client.get_likes(uri="at://did:plc:sme75d7sju4ttl2ew3bexf6c/app.bsky.feed.post/3lbmfnufn2s2c")
for like in res.likes:
print(like.actor.handle, like.actor.display_name)
matthewstadlen.bsky.social
(…省略)
自分がいいねしたポスト一覧
res = client.app.bsky.feed.get_actor_likes({"actor":"nekoniiii.com"})
for feed in res.feed:
print(feed.post.author.handle, feed.post.author.display_name, feed.post.record.text)
kcns.bsky.social 梔 最近の猫
(…省略)
"get_actor_likes"という名前から任意のユーザのいいねが見れるかと思いきや、自分のしか見れません。(他のユーザーはエラーになります)
「今後解禁する…?」のかもしれません。
おわりに
XのAPIと比べて利用までが大変だったり、直感的にわかりづらい点が多い気もしました。(特にURIですぐにポストが確認出来ないのが面倒でした…)
理解できてない部分も大きいのでこれから学びたいと思います。
紹介できたのはほんの一部の機能ですが、ご参考にして下さい。