4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Pythonライブラリ pixivpy】ログイン認証変更の対処法について(2021)

Last updated at Posted at 2021-02-26

pixivpyってなんぞ?

Pythonを使って人気サイトpixivにてタグ検索やイラスト保存できる
優れライブラリのことです。
https://github.com/upbit/pixivpy

筆者もhttps://twitter.com/PixSns
にてpixiv デイリーランキング上位3位を自動ツイートしてます。
pixiv絵師様について知っていただければ嬉しい!と思い活動中。

pixivpyの認証方法が変更

2021年2月下旬頃、pixivpyの認証方法が変更されました。
従来では、pixivのユーザー名・パスワードがauth認証として必要でしたが、
今後はrefresh_tokenを用いることで動作するそうです。

refresh_tokenの取得方法

pixiv_auth.py
#!/usr/bin/env python

from argparse import ArgumentParser
from base64 import urlsafe_b64encode
from hashlib import sha256
from pprint import pprint
from secrets import token_urlsafe
from sys import exit
from urllib.parse import urlencode
from webbrowser import open as open_url

import requests

# Latest app version can be found using GET /v1/application-info/android
USER_AGENT = "PixivAndroidApp/5.0.234 (Android 11; Pixel 5)"
REDIRECT_URI = "https://app-api.pixiv.net/web/v1/users/auth/pixiv/callback"
LOGIN_URL = "https://app-api.pixiv.net/web/v1/login"
AUTH_TOKEN_URL = "https://oauth.secure.pixiv.net/auth/token"
CLIENT_ID = "MOBrBDS8blbauoSck0ZfDbtuzpyT"
CLIENT_SECRET = "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj"


def s256(data):
    """S256 transformation method."""

    return urlsafe_b64encode(sha256(data).digest()).rstrip(b"=").decode("ascii")


def oauth_pkce(transform):
    """Proof Key for Code Exchange by OAuth Public Clients (RFC7636)."""

    code_verifier = token_urlsafe(32)
    code_challenge = transform(code_verifier.encode("ascii"))

    return code_verifier, code_challenge


def print_auth_token_response(response):
    data = response.json()

    try:
        access_token = data["access_token"]
        refresh_token = data["refresh_token"]
    except KeyError:
        print("error:")
        pprint(data)
        exit(1)

    print("access_token:", access_token)
    print("refresh_token:", refresh_token)
    print("expires_in:", data.get("expires_in", 0))


def login():
    code_verifier, code_challenge = oauth_pkce(s256)
    login_params = {
        "code_challenge": code_challenge,
        "code_challenge_method": "S256",
        "client": "pixiv-android",
    }

    open_url(f"{LOGIN_URL}?{urlencode(login_params)}")

    try:
        code = input("code: ").strip()
    except (EOFError, KeyboardInterrupt):
        return

    response = requests.post(
        AUTH_TOKEN_URL,
        data={
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
            "code": code,
            "code_verifier": code_verifier,
            "grant_type": "authorization_code",
            "include_policy": "true",
            "redirect_uri": REDIRECT_URI,
        },
        headers={"User-Agent": USER_AGENT},
    )

    print_auth_token_response(response)


def refresh(refresh_token):
    response = requests.post(
        AUTH_TOKEN_URL,
        data={
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
            "grant_type": "refresh_token",
            "include_policy": "true",
            "refresh_token": refresh_token,
        },
        headers={"User-Agent": USER_AGENT},
    )
    print_auth_token_response(response)


def main():
    parser = ArgumentParser()
    subparsers = parser.add_subparsers()
    parser.set_defaults(func=lambda _: parser.print_usage())
    login_parser = subparsers.add_parser("login")
    login_parser.set_defaults(func=lambda _: login())
    refresh_parser = subparsers.add_parser("refresh")
    refresh_parser.add_argument("refresh_token")
    refresh_parser.set_defaults(func=lambda ns: refresh(ns.refresh_token))
    args = parser.parse_args()
    args.func(args)


if __name__ == "__main__":
    main()

####①上記のコードを実行。

####②Pixivログインページでブラウザが開きます。

####③開発コンソール(F12)を開き、[ネットワーク]タブに切り替えます。

####④検索ボックスにcallback? を入力

####⑤Pixivにログインする。

####⑥ログイン後、空白のページが表示。
callback?state=...&code=...。codeパラメータの値をpixiv_auth.pyのプロンプトにコピーして、Enterキーを押します。

####⑦refresh_token表示がされる。

⚠️ codeの有効期限は非常に短いため、手順5と7の間の処理は素早くすること。

auth認証をrefresh_tokenに変更で動作

# api.login(_USERNAME, _PASSWORD) # 従来ではpixivのID/PWが必要だった。
api.auth(refresh_token=_REFRESH_TOKEN) # 新auth認証ではrefresh_tokenでok。

https://github.com/upbit/pixivpy/commit/249eb51f202ba83868ec358ed7bab4163c0f8cc6
ソース元 Build Status PyPI version

Due to #158 reason, password login no longer exist. Please use api.auth(refresh_token=REFRESH_TOKEN) instead
Due to #158 reason, password login no longer exist. Please use api.auth(refresh_token=REFRESH_TOKEN) instead

To get refresh_token, see @ZipFile Pixiv OAuth Flow or OAuth with Selenium/ChromeDriver
Pixiv API for Python (with Auth supported)

https://gist.github.com/ZipFile/c9ebedb224406f4f11845ab700124362
https://github.com/upbit/pixivpy/commit/249eb51f202ba83868ec358ed7bab4163c0f8cc6

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?