ブラックボックス

プログラミングのノウハウやライフハックをどんどん投稿していきたい

Feb 15, 2024 - 3 minute read - ノウハウ

【Python】BlueskyにAPI経由で投稿する

Blueskyが招待制ではなくなったので色々試してます。
その中でPythonを利用してBlueskyにAPIから投稿してみたので、そのメモを記載します。

参考


はじめに

Pythonのバージョンは3.7.1以降が必要となります。

SDKのインストール

SDKとして提供されているThe AT Protocol SDKをPIPでインストールします。

pip install atproto

テキストのみの投稿

基本的に参考リンクに記載している通りで出来てしまいますが、以下のコードでテキストが投稿されます。

from atproto import Client

client = Client()
client.login(ユーザID or メールアドレス, パスワード)

client.send_post(text='Hello World!')

ユーザIDは@以降の文字列すべてを入力する必要があります。
つまり、以下画像の赤枠内のxxx.bsky.socialまでです。
ユーザID

画像つきの投稿

やり方は3通り紹介されています。

  • 1:

    from atproto import Client, models
    
    client = Client()
    client.login(ユーザID or メールアドレス, パスワード)
    
    with open('画像のパス', 'rb') as f:
        img_data = f.read()
    
        upload = client.upload_blob(img_data)
        images = [models.AppBskyEmbedImages.Image(alt='画像のALTに設定するテキスト', image=upload.blob)]
        embed = models.AppBskyEmbedImages.Main(images=images)
    
        client.com.atproto.repo.create_record(
            models.ComAtprotoRepoCreateRecord.Data(
                repo=client.me.did,
                collection=models.ids.AppBskyFeedPost,
                record=models.AppBskyFeedPost.Record(
                    created_at=client.get_current_time_iso(), text='投稿するテキスト', embed=embed
                ),
            )
        )
    
  • 2:

    from atproto import Client, models
    
    client = Client()
    client.login(ユーザID or メールアドレス, パスワード)
    
    with open('画像のパス', 'rb') as f:
        img_data = f.read()
    
        upload = client.upload_blob(img_data)
        images = [models.AppBskyEmbedImages.Image(alt='画像のALTに設定するテキスト', image=upload.blob)]
        embed = models.AppBskyEmbedImages.Main(images=images)
    
        post = models.AppBskyFeedPost.Record(text='投稿するテキスト', embed=embed, created_at=client.get_current_time_iso())
        client.app.bsky.feed.post.create(client.me.did, post)
    
  • 3:

    from atproto import Client
    
    client = Client()
    client.login(ユーザID or メールアドレス, パスワード)
    
    with open('画像のパス', 'rb') as f:
        img_data = f.read()
    
        client.send_image(text='投稿するテキスト', image=img_data, image_alt='画像のALTに設定するテキスト')
    

注意点として、投稿出来る画像のサイズは1,000,000バイトまでとなります。
1MBには微妙に足りておらず、キロバイト換算でおおよそ976.56KBなので注意が必要です。
サイズ超過の場合は以下のようなエラーが返ります。

atproto_client.exceptions.BadRequestError: Response(success=False, status_code=400, content=XrpcError(error='BlobTooLarge', message='This file is too large. It is 1021.88KB but the maximum size is 976.56KB.'), headers=Headers({'date': 'Thu, 15 Feb 2024 00:08:48 GMT', 'content-type': 'application/json; charset=utf-8', 'content-length': '110', 'connection': 'keep-alive', 'x-powered-by': 'Express', 'access-control-allow-origin': '*', 'ratelimit-limit': '5000', 'ratelimit-remaining': '4979', 'ratelimit-reset': '1708004956', 'ratelimit-policy': '5000;w=3600', 'etag': 'W/"6e-Cmj2fgUStkyaFUxc9h9n/JMWgQc"', 'vary': 'Accept-Encoding'}))

エラーメッセージに記載の通り、上記は1021.88KB、つまり1MB未満の画像を投稿しようとして出たエラーです。
この辺りはもう少し緩和してほしいな、と思う次第です。

おわりに

以上のコードを使い、botを作って遊んでみようかと思っています。
また、今回特に言及はしませんでしたが、botはレート制限が設定されているので、それを超過しないようコントロールをする必要があります。
制限は以下のページを参考にしてみてください。
Rate Limits | Bluesky