upbit / pixivpy

Pixiv API for Python
https://pypi.org/project/PixivPy3/#files
The Unlicense
1.8k stars 147 forks source link

Get illust/detail endpoint #100

Closed kaecy closed 5 years ago

kaecy commented 5 years ago

Doesn't work. https://github.com/upbit/pixivpy/blob/master/pixivpy3/aapi.py#L141 You need access_token inside the params.

Like this

app_server = "https://app-api.pixiv.net"
access_token = login()

# gets illustration info of something posted on pixiv using illust_id
def getInfo(illust_id):
    uri = app_server + '/v1/illust/detail'
    params = {
        'illust_id': illust_id,
        'access_token': access_token
    }
    headers = {
        'user-agent': 'rak'
    }
    req = urllib2.Request(uri + '?' + urllib.urlencode(params), headers=headers)
    file = urllib2.urlopen(req)
    data = file.read()
    print data
Mikubill commented 5 years ago

I did a test and it looks like illust_detail still works. Can you provide more information when illust_detail doesn't work?

kaecy commented 5 years ago

Um a simple test like API.get_detail("77723683"). It doesn't work the way I was doing it before. This is how it is in the current code here https://github.com/upbit/pixivpy/blob/master/pixivpy3/aapi.py#L141 This uses the "headers['Authorization'] = 'Bearer %s' % self.access_token" which doesn't work anymore.

You can even test it here: https://app-api.pixiv.net/v1/illust/detail?illust_id=77723683

kaecy commented 5 years ago

This codebase is over complicated. I use a simpler version of it. Like this

from datetime import datetime
from md5 import md5
import json, urllib, urllib2

headers = {
    'user-agent': 'PixivAndroidApp/5.0.64 (Android 6.0)',
    'host': 'oauth.secure.pixiv.net'
}

app_server = "https://app-api.pixiv.net";
access_token = ""
client_hash = "28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c"

def login(username, password):
    global headers
    global access_token

    auth_uri = 'https://oauth.secure.pixiv.net/auth/token'

    local_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S+00:00')
    headers['x-client-time'] = local_time;
    headers['x-client-hash'] = md5(local_time + client_hash).hexdigest()

    data = {
        'grant_type': 'password',
        'client_id': 'MOBrBDS8blbauoSck0ZfDbtuzpyT',
        'client_secret': 'lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj',
        'password': password,
        'username': username
    }

    # request
    req = urllib2.Request(auth_uri, urllib.urlencode(data), headers=headers)
    try:
        file = urllib2.urlopen(req)
        data = file.read()
        #print data
        metaData = json.loads(data)
        # headers["authorization"] = "Bearer " + meta["response"]["access_token"]
        access_token = metaData['response']['access_token']
        # save the refresh token once. it doesn't change.
    except urllib2.HTTPError, error:
        print error.read()
        return 1

# gets illustration info of something posted on pixiv using illust_id
def getInfo(illust_id):
    uri = app_server + '/v1/illust/detail'
    params = {
        'illust_id': illust_id,
        'access_token': access_token
    }
    headers = {
        'user-agent': 'rak'
    }
    req = urllib2.Request(uri + '?' + urllib.urlencode(params), headers=headers)
    file = urllib2.urlopen(req)
    return json.loads(file.read())

A program would be...

import pixie_thief

if pixie_thief.login("****", "****") > 0:
    print "error logging in"
    exit(1)

illust_id = "77723683"
metaData = pixie_thief.getInfo(illust_id)
Mikubill commented 5 years ago

Thanks for the code you provided, I will test it later. But I still can't reproduce this problem. Can you run the following code and tell me the output?

# For Python 3
import pixivpy3
import sys
print(sys.version)
print(pixivpy3.__version__)
api = pixivpy3.AppPixivAPI()
api.login("userbay","userpay")
print(api.illust_detail(77723683))

# For Python 2
import pixivpy3
import sys
print sys.version
print pixivpy3.__version__ 
api = pixivpy3.AppPixivAPI()
api.login("userbay","userpay")
print api.illust_detail(77723683)
kaecy commented 5 years ago

Sorry can't do it. There's too many dependencies. Requests, urllib3, certifi, chardet, idna... I gave up after that. I don't use pixivpy but the code is pretty much the same. With the access_token in the Authorization Header I get: urllib2.HTTPError: HTTP Error 400: Bad Request exception. It works good if the access_token is in the params like in the getInfo method.

kaecy commented 5 years ago

I'm a python 2 fan. 👍

Mikubill commented 5 years ago

You can try...(Note that the token may expire)

curl -i "https://app-api.pixiv.net/v1/illust/detail?illust_id=77723683"  -H "Authorization: Bearer qNdVACZ8U6_4Qr_RJ61wOPsSZ9BWxqtePeypuZjMt4M"

Then it will return the correct result.

kaecy commented 5 years ago

Yeah that works. I didn't know I had curl installed.

where curl
> C:\Windows\System32\curl.exe
curl --version
> curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL
upbit commented 5 years ago

If curl works, it means the Authorization: Bearer <BearerToken> method still worked. If it won't work, check self.access_token in your AppPixivAPI().

So, can you provide the execution result of the following code? (Just install dependencies by pip)

Upgrade pixivpy to the latest version: pip install pixivpy --upgrade

import sys
import pixivpy3
from pixivpy3.bapi import ByPassSniApi

print(sys.version)
print(pixivpy3.__version__)

# api = AppPixivAPI()
api = ByPassSniApi()  # same as AppPixivAPI, but bypass the GFW
api.require_appapi_hosts()
token = api.login("userbay", "userpay")

print(token)
print(api.illust_detail(77723683))
Mikubill commented 5 years ago

There's too many dependencies. Requests, urllib3, certifi, chardet, idna... I gave up after that. I don't use pixivpy but the code is pretty much the same.

You can check if your implementation has errors. Note: Through some small tests I found that 400 Bad Request may be caused by this reason:

curl -i "https://app-api.pixiv.net/v1/illust/detail?illust_id=-1"  -H "Authorization: Bearer qNdVACZ8U6_4Qr_RJ61wOPsSZ9BWxqtePeypuZjMt4M"

< HTTP/2 400
< server: nginx
< content-length: 146

curl -i "https://app-api.pixiv.net/v1/illust/detail?illust_id='-1'"  -H "Authorization: Bearer qNdVACZ8U6_4Qr_RJ61wOPsSZ9BWxqtePeypuZjMt4M"

< HTTP/2 400
< server: nginx
< content-length: 146
kaecy commented 5 years ago

I don't know what it is. It could be the urllib2 lib. I think I tried everything to make it work. But for now it works when the token is in the params.

kaecy commented 5 years ago

Thank you! You guys have been so helpful. It works now with the authorization header. I think I was causing the errors somehow.

Working code:

# gets illustration info of something posted on pixiv using illust_id
def getInfo(illust_id):
    uri = app_server + '/v1/illust/detail'
    params = {
        'illust_id': illust_id
    }
    headers = {
        'user-agent': 'rak',
        'authorization': "Bearer " + access_token
    }
    req = urllib2.Request(uri + '?' + urllib.urlencode(params), headers=headers)
    file = urllib2.urlopen(req)
    return json.loads(file.read())

This gives you a json object of the illust's meta data. Python 2 FTW!

Mikubill commented 5 years ago

The problem seems to have been solved. If there are no more questions, consider closing this issue...?