it-swarm.com.ru

Как сделать почтовый запрос с библиотекой запросов Python?

Я использую следующие фильтры в Postman для выполнения запроса POST в Web API, но я не могу сделать простой запрос POST в Python с библиотекой запросов. 

Сначала, я отправляю POST запрос на этот URL ( http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets ) с следующие фильтры в Postman применяются к телу с выбранными параметрами raw и JSON (application/json). 

Filters in Postman

{
  "filter": {
    "filters": [
      {
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
      },
      {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
      },
      {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
      },
      {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
      }],
     "logic": "and"
    }
}

База данных, в которой хранятся данные, - Cassandra, и по следующим ссылкам оператор Cassandra не равен , оператор Cassandra OR , Cassandra Между порядком операторов , Cassandra не поддерживает NOT EQUAL TO, ИЛИ, МЕЖДУ, поэтому я не могу отфильтровать URL с этими операторами, за исключением И

Second, я использую следующий код для применения простого фильтра с библиотекой запросов. 

import requests
payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=payload)

Но у меня есть полные данные о билетах, а не только те, которые не являются временной деградацией. 

В-третьих, система на самом деле работает, но мы наблюдаем задержку в 2-3 минуты для просмотра данных. Логика выглядит следующим образом: У нас 8 пользователей, и мы хотим видеть все заявки на пользователя, которые не являются временной деградацией, тогда мы делаем:

def get_json():
    if user_name == "user 001":
        with urllib.request.urlopen(
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&001",timeout=15) as url:
            complete_data = json.loads(url.read().decode())

    Elif user_name == "user 002":
        with urllib.request.urlopen(             
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&002",timeout=15) as url:
            complete_data = json.loads(url.read().decode())
    return complete_data

def get_tickets_not_temp_degradation(start_date,end_date,complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

По сути, мы получаем полный набор билетов за текущий и прошлый год, затем мы позволяем Python отфильтровывать полный набор по пользователю, и пока что есть только 10 пользователей, что означает, что этот процесс повторяется 10 раз, и я не удивляюсь Узнайте, почему мы получаем задержку ... 

Мои вопросы, как я могу исправить эту проблему библиотеки запросов? Я использую следующую ссылку запрашивает библиотечную документацию как учебное пособие, чтобы заставить его работать, но просто кажется, что моя полезная нагрузка не читается.

6
Alejandro BR

Ваш запрос почтальона является телом JSON. Просто воспроизведите то же самое тело на Python. Ваш код Python не отправляет JSON и не отправляет те же данные, что и ваш пример Postman.

Для начала, отправка словаря через аргументы data кодирует этот словарь в форму application/x-www-form-urlencoded, а не в JSON. Во-вторых, вы, кажется, отправляете один фильтр.

Следующий код точно копирует вашу почту:

import requests

filters = {"filter": {
    "filters": [{
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
    }, {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
    }, {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
    }, {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
    }],
    "logic": "and"
}}

url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
response = requests.post(url, json=filters)

Обратите внимание, что filters здесь представляет собой структуру данных Python, и что она передается в аргументе ключевого слова json. Использование последнего делает две вещи:

  • Кодируйте структуру данных Python в JSON (производя то же самое значение JSON, что и ваше необработанное значение тела Postman).
  • Установите для заголовка Content-Type значение application/json (как вы делали в своей конфигурации Postman, выбрав опцию JSON в раскрывающемся меню после выбора raw для тела).

В противном случае requests это просто HTTP API, он не может заставить Cassandra делать больше, чем любая другая HTTP-библиотека. Код urllib.request.urlopen отправляет запросы GET и тривиально переводится в requests с помощью:

def get_json():
    url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
    response = requests.get(url, params={'user_name': user}, timeout=15)    
    return response.json()

Я удалил ветвление if и заменил его с помощью аргумента params, который переводит словарь пар ключ-значение в правильно закодированный URL-запрос (передавая имя пользователя как ключ user_name).

Обратите внимание на вызов json() в ответе; это заботится о декодировании данных JSON, возвращаемых с сервера. Это все еще занимает много времени, здесь вы не сильно фильтруете данные Кассандры.

9
Martijn Pieters

Я бы рекомендовал использовать атрибут json вместо данных. Он обрабатывает демпинг для вас.

import requests

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, json=data)

Обновление, ответьте на вопрос 3. Есть ли причина, по которой вы используете urllib? Я бы также использовал запросы Python для этого запроса.

import requests

def get_json():
    r = requests.get("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets”, params={"user_name": user_name.replace(" ", "&")})

    return r.json

# not sure what you’re doing here, more context/code example would help
def get_tickets_not_temp_degradation(start_date, end_date, complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

Кроме того, действительно ли имя пользователя должно быть user+001, а не user&001 или user 001?

4
teewuane

Мой опыт таков: я пробовал urllib и много запросов на python для работы с API. Это просто очень проблематично. Обычно запросы GET являются прямыми, но запросы POST очень проблематичны. Иногда не работает (как в вашем случае с полезной нагрузкой), или, что еще хуже, работает плохо. Недавно у меня был этот сценарий, который прошел мои тесты, но он не работал в некоторых случаях на производстве, пока я не узнал, что запросы, содержащие специальные символы (например, á á на португальском языке), не работают. :(
В какой-то момент я сказал «к черту эти зависимости черного ящика». На самом деле, можно сделать любой вызов API без Python или любого другого языка сценариев (ну, по крайней мере, вам нужен bash). Как пользователь UNIX можно использовать CURL для ВСЕГО. Это освобождает! Нет больше примеров, которые не работают, больше нет версий языков, нет больше библиотек http. Я просто отправляю запрос скручивания из терминала и вижу, работает ли то, что я хочу. Ваш случай будет:

curl -H "Content-Type: application/json" -d '{"field":"T_Subcategory","operator":"neq","value":"Temporary Degradation"}' "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"

Далее я создаю следующий скрипт на Python для GET:

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

Для POST:

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

data = {"my":"phyton_dictionary"}
data = json.dumps(data) #this is a json string now

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, -d, data, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

Эти два прототипа очень легко преобразовать в функции Python и создать «библиотеку», если вам нужны другие вызовы. Вы можете создать параметры URL вручную, если вы имеете дело с API, который в этом нуждается.

Таким образом, этот ответ не решает вашу конкретную проблему с запросами. Это просто говорит вам, что у меня было много таких проблем, я решил несколько из них методом проб и ошибок, и в конце концов решил проблему, изменив способ построения скрипта API, удалив все зависимости, которые мог, пока не достиг очень чистый сценарий. Никогда больше не возникало проблем, если в документах есть URL-адрес, который мне нужен, и заголовки, которые мне нужно отправить. 

Надеюсь, поможет.

0
Alex

Я думаю, вы можете использовать библиотеку запросов следующим образом:

import requests
import json

payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=json.dumps(payload))
0
juanblo

Вы отправляете пользователя в URL, используйте его по почте, но это зависит от того, как реализованы конечные точки. Вы можете попробовать следующий код:

import requests
from json import dumps

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, data=dumps(data))
0
anuj249