Python 3.5 / Pastebin "Неверный запрос API, неверный api_option"
Я работаю над дерганным irc-ботом, и одним из компонентов, которые я хотел получить, была возможность для бота сохранять кавычки в пастинную пасту при закрытии, а затем извлекать те же кавычки при запуске.
Я начал с части, посвященной сохранению, и натолкнулся на блокпост, где я не могу получить действительное сообщение и не могу найти метод.
#!/usr/bin/env python3
import urllib.parse
import urllib.request
# --------------------------------------------- Pastebin Requisites --------------------------------------------------
pastebin_key = 'my pastebin key' # developer api key, required. GET: http://pastebin.com/api
pastebin_password = 'password' # password for pastebin_username
pastebin_postexp = 'N' # N = never expire
pastebin_private = 0 # 0 = Public 1 = unlisted 2 = Private
pastebin_url = 'http://pastebin.com/api/api_post.php'
pastebin_username = 'username' # user corresponding with key
# --------------------------------------------- Value clean up --------------------------------------------------
pastebin_password = urllib.parse.quote(pastebin_password, safe='/')
pastebin_username = urllib.parse.quote(pastebin_username, safe='/')
# --------------------------------------------- Pastebin Functions --------------------------------------------------
def post(title, content): # used for posting a new paste
pastebin_vars = {'api_option': 'paste', 'api_user_key': pastebin_username, 'api_paste_private': pastebin_private,
'api_paste_name': title, 'api_paste_expire_date': pastebin_postexp, 'api_dev_key': pastebin_key,
'api_user_password': pastebin_password, 'api_paste_code': content}
try:
str_to_paste = ', '.join("{!s}={!r}".format(key, val) for (key, val) in pastebin_vars.items()) # dict to str :D
str_to_paste = str_to_paste.replace(":", "") # remove :
str_to_paste = str_to_paste.replace("'", "") # remove '
str_to_paste = str_to_paste.replace(")", "") # remove )
str_to_paste = str_to_paste.replace(", ", "&") # replace dividers with &
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
print('did that work?')
except:
print("post submit failed :(")
print(pastebin_url + "?" + str_to_paste) # print the output for test
post("test", "stuff")
Я открыт для импорта большего количества библиотек и прочего, но не совсем уверен, что я делаю неправильно после двух дней работы над этим:S
4 ответа
Во-первых, ваш try
/except
блок выбрасывает фактическую ошибку. Вы почти никогда не должны использовать "голые" except
пункт без захвата или повторного поднятия исходного исключения. Смотрите эту статью для полного объяснения.
Как только вы удалите try
/except
, и вы увидите основную ошибку:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "paste.py", line 42, in post
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
File "/usr/lib/python3.4/urllib/request.py", line 161, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.4/urllib/request.py", line 461, in open
req = meth(req)
File "/usr/lib/python3.4/urllib/request.py", line 1112, in do_request_
raise TypeError(msg)
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
Это означает, что вы пытаетесь передать строку юникода в функцию, которая ожидает байты. Когда вы выполняете ввод / вывод (например, чтение / запись файлов на диск или отправку / получение данных по HTTP), вам, как правило, необходимо кодировать любые строки Юникода в байтах. Посмотрите эту презентацию для хорошего объяснения Unicode против байтов и когда вам нужно кодировать и декодировать.
Далее эта строка:
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
Выбрасывает ответ, поэтому у вас нет возможности узнать результат вашего вызова API. Присвойте это переменной или верните ее из вашей функции, чтобы вы могли затем проверить значение. Это будет либо URL для вставки, либо сообщение об ошибке от API.
Далее, я думаю, что ваш код отправляет множество ненужных параметров в API и ваш str_to_paste
заявления не нужны.
Мне удалось сделать вставку, используя следующий, гораздо более простой код:
import urllib.parse
import urllib.request
PASTEBIN_KEY = 'my-api-key' # developer api key, required. GET: http://pastebin.com/api
PASTEBIN_URL = 'http://pastebin.com/api/api_post.php'
def post(title, content): # used for posting a new paste
pastebin_vars = dict(
api_option='paste',
api_dev_key=PASTEBIN_KEY,
api_paste_name=title,
api_paste_code=content,
)
return urllib.request.urlopen(PASTEBIN_URL, urllib.parse.urlencode(pastebin_vars).encode('utf8')).read()
Здесь это используется:
>>> post("test", "hello\nworld.")
b'http://pastebin.com/v8jCkHDB'
import urllib.parse
import urllib.request
PASTEBIN_KEY = 'xxx'
PASTEBIN_URL = 'https://pastebin.com/api/api_post.php'
PASTEBIN_LOGIN_URL = 'https://pastebin.com/api/api_login.php'
PASTEBIN_LOGIN = 'my_login_name'
PASTEBIN_PWD = 'yyy'
def pastebin_post(title, content):
login_params = dict(
api_dev_key=PASTEBIN_KEY,
api_user_name=PASTEBIN_LOGIN,
api_user_password=PASTEBIN_PWD
)
data = urllib.parse.urlencode(login_params).encode("utf-8")
req = urllib.request.Request(PASTEBIN_LOGIN_URL, data)
with urllib.request.urlopen(req) as response:
pastebin_vars = dict(
api_option='paste',
api_dev_key=PASTEBIN_KEY,
api_user_key=response.read(),
api_paste_name=title,
api_paste_code=content,
api_paste_private=2,
)
return urllib.request.urlopen(PASTEBIN_URL, urllib.parse.urlencode(pastebin_vars).encode('utf8')).read()
rv = pastebin_post("This is my title", "These are the contents I'm posting")
print(rv)
Объединение двух разных ответов выше дало мне это рабочее решение.
Я не знал о пастбине до сих пор. Я прочитал их API и попробовал это в первый раз, и он работал отлично.
Вот что я сделал:
- Я вошел в систему, чтобы получить
api_user_key
, - Включено, что в публикации вместе с
api_dev_key
, - Проверил сайт, и пост был там.
Вот код:
import urllib.parse
import urllib.request
def post(url, params):
data = urllib.parse.urlencode(login_params).encode("utf-8")
req = urllib.request.Request(login_url, data)
with urllib.request.urlopen(req) as response:
return response.read()
# Logging in to fetch api_user_key
login_url = "http://pastebin.com/api/api_login.php"
login_params = {"api_dev_key": "<the dev key they gave you",
"api_user_name": "<username goes here>",
"api_user_password": "<password goes here>"}
api_user_key = post(login_url, login_params)
# Posting some random text
post_url = "http://pastebin.com/api/api_post.php"
post_params = {"api_dev_key": "<the dev key they gave you",
"api_option": "paste",
"api_paste_code": "<head>Testing</head>",
"api_paste_private": "0",
"api_paste_name": "testing.html",
"api_paste_expire_date": "10M",
"api_paste_format": "html5",
"api_user_key": api_user_key}
response = post(post_url, post_params)
Только первые три параметра необходимы для публикации чего-либо, остальные являются необязательными.
fwy API, похоже, не принимает HTTP-запросы на момент написания этого, поэтому убедитесь, что URL-адреса в формате
https://pas...