Get data for JSON Python second List - python

Hoping you are good
I am trying to get data from zendisk by API and Python Json
i can get any data Value under Audits LikeTicket_id and auther_id but when tried get data under Events such as Body
keep get this error
print(audit['body'])
KeyError: 'body'
JSON Output
{
"audits":[
{
"id":1727876301271,
"ticket_id":54010951,
"created_at":"2021-10-21T10:58:06Z",
"author_id":12306596687,
"metadata":{
"system":{
"client":"GuzzleHttp/6.2.1 curl/7.29.0 PHP/7.1.2",
"ip_address":"x.x.x.x",
"location":"Boardman, OR, United States",
"latitude":45.8491,
"longitude":-119.7143
},
"custom":{
}
},
"events":[
{
"id":1727876301291,
"type":"Comment",
"author_id":366289833251,
"body":"Sehr geehrte Damen und Herren,\n\nIn unserer Bestellung fehlt das Kleid, es war nicht mit dabei, obwohl es hätte drin sein müssen.\nFreundliche Grüße",
"attachments":[
],
"audit_id":1727876301271
},
{
"id":1727876301311,
"type":"Create",
"value":"366289833251",
"field_name":"requester_id"
},
Python Code
import requests
import csv
# Settings
auth = 'xxxxxxx', 'xxxxxx'
view_tickets = []
view_id = 214459268
view_audits = []
ticket_id = 54010951
view_events =[]
print(f'Getting tickets from ticket_id ID {ticket_id}')
url = f'https://xxxx.zendesk.com/api/v2/tickets/54010951/audits.json'
while url:
response = requests.get(url, auth=auth)
page_data = response.json()
audits = page_data['audits'] # extract the "tickets" list from the page
view_audits.extend(audits)
url = page_data['next_page']
for audit in audits:
print(audit['body'])

You know you're overwriting, not adding, to audits right? (in this line: audits = page_data['audits']). I don't think that makes sense, but it's hard to know your intent.
To fix the error itself, your json structure has the body key inside the events key. So you can access it with:
print(audit['events'][0]['body'])
or, using another loop:
for audit in audits:
for event in audit['events']
print(event['body'])
You might get an error for the 2nd one because it doesn't appear to have the body key. You can add an if statement to handle that if you want.

Related

Firebase delete method

i have a json in Realtime firebase that look something like that :
{
"-NMtZNTISnGhT-rdibeb": {
"motorista": "Jose",
"plate": "IZC2F45",
"produto": "caroco",
"transp": "VIDAL"
},
"-NN1zI2MHFtbi6G5qUvR": {
"motorista": "ANTONIO",
"plate": "AWJ-9353",
"produto": "CAROCO",
"transp": "GRANLIDER"
}
}
I'm working with a python code that sould delete a select line from a Treeview(Tkinter) and also delete from this database. The method Delete is called from a Button(tkinter). Actually he delete only the select line from Treeview, but don't delete from database.
def delete(self):
selected_item = self.tree.selection()
if selected_item:
id = self.tree.item(selected_item, "text")
url = self.base_url + id + '.json'
response = requests.delete(url)
print(url)
print(response)
if response.status_code == 200:
self.tree.delete(selected_item)
messagebox.showinfo("Info", "Linha deletada com sucesso!")
else:
messagebox.showerror("Erro", "Não foi possível deletar a linha!")
else:
messagebox.showerror("Erro", "Nenhum item selecionado para deletar!")
also, i made 2 prints to check what he gave me. and this is what i got from prints:
ttps://fila2-6bd6b-default-rtdb.firebaseio.com/-NNh38XBrRen17bGWHga.json
<Response [200]>
already tried chatgpt, reddit. Already check the Rules from laboratory in firebase and he allowed to use Delete, get, update.
https://github.com/ChristopherMachad/truckQueueOnline/blob/main/Main.py

How to load elastic data in python using scroll?

I have an index in elastic search which is having huge data. I am trying to load some of its data (more than 10000 records)in python for further processing. As per documentation and web search scroll is used but it is able to fetch only few records. After sometime this exception occurs,
errorNotFoundError(404, 'search_phase_execution_exception', 'No search context found for id [101781]')
My code is as following:
from elasticsearch import Elasticsearch
##########elastic configuration
host='localhost'
port=9200
user=''
pasw=''
el_index_name = 'test'
es = Elasticsearch([{'host':host , 'port': port}], http_auth=(user,pasw))
res = es.search(index=el_index_name, body={"query": {"match_all": {}}},scroll='10m')
rows=[]
while True:
try:
rows.append(es.scroll(scroll_id=res['_scroll_id'])['hits']['hits'])
except Exception as esl:
print ('error{}'.format(esl))
break
##deleting scroll
es.clear_scroll(scroll_id=res['_scroll_id'])
I have changed the value of scroll='10m' but still, this exception occurs.
You need to change your scroll request line to this:
rows.append(es.scroll(scroll_id=res['_scroll_id'], body={"scroll": "10m","scroll_id": res['_scroll_id']})['hits']['hits'])
As an advice, It is better to increase number of retrieved posts. retrieving just 1 post in each request have negative influence on your performance and it has overhead for your cluster, as well. as an example:
{
"query": {
"match_all": {}
},"size":100
}
I have added the below part to answer to the question in comments. It is not stopping because you have put While True in your code. You need to change it to this:
res = es.search(index=el_index_name, body={"query": {"match_all": {}}}, scroll='10m')
scroll_id = res['_scroll_id']
query = {
"scroll": "10m",
"scroll_id": scroll_id
}
rows = []
while len(res['hits']['hits']):
for item in res['hits']['hits']:
rows.append(item)
res = es.scroll(scroll_id=scroll_id, body=query)
Please let me know if there was any problem with this.

Why am I getting this error "TypeError: string indices must be integers" when trying to fetch data from an api?

json file =
{
"success": true,
"terms": "https://curr
"privacy": "https://cu
"timestamp": 162764598
"source": "USD",
"quotes": {
"USDIMP": 0.722761,
"USDINR": 74.398905,
"USDIQD": 1458.90221
}
}
The json file is above. i deleted lot of values from the json as it took too many spaces. My python code is in below.
import urllib.request, urllib.parse, urllib.error
import json
response = "http://api.currencylayer.com/live?access_key="
api_key = "42141e*********************"
parms = dict()
parms['key'] = api_key
url = response + urllib.parse.urlencode(parms)
mh = urllib.request.urlopen(url)
source = mh.read().decode()
data = json.loads(source)
pydata = json.dumps(data, indent=2)
print("which curreny do you want to convert USD to?")
xm = input('>')
print(f"Hoe many USD do you want to convert{xm}to")
value = input('>')
fetch = pydata["quotes"][0]["USD{xm}"]
answer = fetch*value
print(fetch)
--------------------------------
Here is the
output
"fetch = pydata["quotes"][0]["USD{xm}"]
TypeError: string indices must be integers"
First of all the JSON data you posted here is not valid. There are missing quotes and commas. For example here "terms": "https://curr. It has to be "terms": "https://curr",. The same at "privacy" and the "timestamp" is missing a comma. After i fixed the JSON data I found a solution. You have to use data not pydata. This mean you have to change fetch = pydata["quotes"][0]["USD{xm}"] to fetch = data["quotes"][0]["USD{xm}"]. But this would result in the next error, which would be a KeyError, because in the JSON data you provided us there is no array after the "qoutes" key. So you have to get rid of this [0] or the json data has to like this:
"quotes":[{
"USDIMP": 0.722761,
"USDINR": 74.398905,
"USDIQD": 1458.90221
}]
At the end you only have to change data["quotes"]["USD{xm}"] to data["quotes"]["USD"+xm] because python tries to find a key called USD{xm} and not for example USDIMP, when you type "IMP" in the input.I hope this fixed your problem.

How can I extract values from Tableau on this webpage

I am trying to extract the "mobility index" values for each state and county from this webpage:
https://www.cuebiq.com/visitation-insights-mobility-index/
The preferred output would be a panel data of place (state/county) by date for all available places and dates.
There is another thread (How can I scrape tooltips value from a Tableau graph embedded in a webpage) with a similar question. I tried to follow the solution there but it doesn't seem to work for my case.
Thanks a lot in advance.
(A way that I have tried is to download PDF files generated from Tableau, which would contain all counties' value on a specific date. However, I still need to find a way to make request for each date in the data. Anyway, let me know if you have a better idea than this route).
This tableau data url doesn't return any data. In fact, it only render images of the values (canvas probably) and I'm guessing it detects click based on coordinate. Probably, it's made this way to cache the value and render quickly.
But when you click on a state, it actually returns data but it seems it doesn't always returns the result for the state (but works the individual county).
The solution I've found is to use the tooltip to get the data for the state. When you click the state, it generates a request like this :
POST https://public.tableau.com/{path}/{session_id}/commands/tabsrv/render-tooltip-server
with the following form param :
worksheet: US Map - State - CMI
dashboard: CMI
tupleIds: [18]
vizRegionRect: {"r":"viz","x":496,"y":148,"w":0,"h":0,"fieldVector":null}
allowHoverActions: false
allowPromptText: true
allowWork: false
useInlineImages: true
where tupleIds: [18] refers to the index of the state in a list of states in reverse alphabetical order like this :
stateNames = ["Wyoming","Wisconsin","West Virginia","Washington","Virginia","Vermont","Utah","Texas","Tennessee","South Dakota","South Carolina","Rhode Island","Pennsylvania","Oregon","Oklahoma","Ohio","North Dakota","North Carolina","New York","New Mexico","New Jersey","New Hampshire","Nevada","Nebraska","Montana","Missouri","Mississippi","Minnesota","Michigan","Massachusetts","Maryland","Maine","Louisiana","Kentucky","Kansas","Iowa","Indiana","Illinois","Idaho","Georgia","Florida","District of Columbia","Delaware","Connecticut","Colorado","California","Arkansas","Arizona","Alabama"]
It gives a json with the html of the tooltip which has the CMI and YoY values you want to extract :
{
"vqlCmdResponse": {
"cmdResultList": [{
"commandName": "tabsrv:render-tooltip-server",
"commandReturn": {
"tooltipText": "{\"htmlTooltip\": \"<HTML HERE WITH THE VALUES>\"}]},\"overlayAnchors\":[]}"
}
}]
}
}
The only caveat is that you'll hava to make one request per state :
import requests
from bs4 import BeautifulSoup
import json
import time
data_host = "https://public.tableau.com"
r = requests.get(
f"{data_host}/views/CMI-2_0/CMI",
params= {
":showVizHome":"no",
}
)
soup = BeautifulSoup(r.text, "html.parser")
tableauData = json.loads(soup.find("textarea",{"id": "tsConfigContainer"}).text)
dataUrl = f'{data_host}{tableauData["vizql_root"]}/bootstrapSession/sessions/{tableauData["sessionid"]}'
r = requests.post(dataUrl, data= {
"sheet_id": tableauData["sheetId"],
})
data = []
stateNames = ["Wyoming","Wisconsin","West Virginia","Washington","Virginia","Vermont","Utah","Texas","Tennessee","South Dakota","South Carolina","Rhode Island","Pennsylvania","Oregon","Oklahoma","Ohio","North Dakota","North Carolina","New York","New Mexico","New Jersey","New Hampshire","Nevada","Nebraska","Montana","Missouri","Mississippi","Minnesota","Michigan","Massachusetts","Maryland","Maine","Louisiana","Kentucky","Kansas","Iowa","Indiana","Illinois","Idaho","Georgia","Florida","District of Columbia","Delaware","Connecticut","Colorado","California","Arkansas","Arizona","Alabama"]
for stateIndex, state in enumerate(stateNames):
time.sleep(0.5) #for throttling
r = requests.post(f'{data_host}{tableauData["vizql_root"]}/sessions/{tableauData["sessionid"]}/commands/tabsrv/render-tooltip-server',
data = {
"worksheet": "US Map - State - CMI",
"dashboard": "CMI",
"tupleIds": f"[{stateIndex+1}]",
"vizRegionRect": json.dumps({"r":"viz","x":496,"y":148,"w":0,"h":0,"fieldVector":None}),
"allowHoverActions": "false",
"allowPromptText": "true",
"allowWork": "false",
"useInlineImages": "true"
})
tooltip = json.loads(r.json()["vqlCmdResponse"]["cmdResultList"][0]["commandReturn"]["tooltipText"])["htmlTooltip"]
soup = BeautifulSoup(tooltip, "html.parser")
rows = [
t.find("tr").find_all("td")
for t in soup.find_all("table")
]
entry = { "state": state }
for row in rows:
if (row[0].text == "Mobility Index:"):
entry["CMI"] = "".join([t.text.strip() for t in row[1:]])
if row[0].text == "YoY (%):":
entry["YoY"] = "".join([t.text.strip() for t in row[1:]])
print(entry)
data.append(entry)
print(data)
Try this on repl.it
To get the county information it's the same as this post using the select endpoint which gives you the data with the same format as the post you've linked in your question
The following will extract data for all county and state :
import requests
from bs4 import BeautifulSoup
import json
import time
data_host = "https://public.tableau.com"
worksheet = "US Map - State - CMI"
dashboard = "CMI"
r = requests.get(
f"{data_host}/views/CMI-2_0/CMI",
params= {
":showVizHome":"no",
}
)
soup = BeautifulSoup(r.text, "html.parser")
tableauData = json.loads(soup.find("textarea",{"id": "tsConfigContainer"}).text)
dataUrl = f'{data_host}{tableauData["vizql_root"]}/bootstrapSession/sessions/{tableauData["sessionid"]}'
r = requests.post(dataUrl, data= {
"sheet_id": tableauData["sheetId"],
})
data = []
stateNames = ["Wyoming","Wisconsin","West Virginia","Washington","Virginia","Vermont","Utah","Texas","Tennessee","South Dakota","South Carolina","Rhode Island","Pennsylvania","Oregon","Oklahoma","Ohio","North Dakota","North Carolina","New York","New Mexico","New Jersey","New Hampshire","Nevada","Nebraska","Montana","Missouri","Mississippi","Minnesota","Michigan","Massachusetts","Maryland","Maine","Louisiana","Kentucky","Kansas","Iowa","Indiana","Illinois","Idaho","Georgia","Florida","District of Columbia","Delaware","Connecticut","Colorado","California","Arkansas","Arizona","Alabama"]
for stateIndex, state in enumerate(stateNames):
time.sleep(0.5) #for throttling
r = requests.post(f'{data_host}{tableauData["vizql_root"]}/sessions/{tableauData["sessionid"]}/commands/tabsrv/render-tooltip-server',
data = {
"worksheet": worksheet,
"dashboard": dashboard,
"tupleIds": f"[{stateIndex+1}]",
"vizRegionRect": json.dumps({"r":"viz","x":496,"y":148,"w":0,"h":0,"fieldVector":None}),
"allowHoverActions": "false",
"allowPromptText": "true",
"allowWork": "false",
"useInlineImages": "true"
})
tooltip = json.loads(r.json()["vqlCmdResponse"]["cmdResultList"][0]["commandReturn"]["tooltipText"])["htmlTooltip"]
soup = BeautifulSoup(tooltip, "html.parser")
rows = [
t.find("tr").find_all("td")
for t in soup.find_all("table")
]
entry = { "state": state }
for row in rows:
if (row[0].text == "Mobility Index:"):
entry["CMI"] = "".join([t.text.strip() for t in row[1:]])
if row[0].text == "YoY (%):":
entry["YoY"] = "".join([t.text.strip() for t in row[1:]])
r = requests.post(f'{data_host}{tableauData["vizql_root"]}/sessions/{tableauData["sessionid"]}/commands/tabdoc/select',
data = {
"worksheet": worksheet,
"dashboard": dashboard,
"selection": json.dumps({
"objectIds":[stateIndex+1],
"selectionType":"tuples"
}),
"selectOptions": "select-options-simple"
})
entry["county_data"] = r.json()["vqlCmdResponse"]["layoutStatus"]["applicationPresModel"]["dataDictionary"]["dataSegments"]
print(entry)
data.append(entry)
print(data)

python post request json

I need to use Python to do a POST request using JSON format. What I have right now is
url = 'http://mysurl.org'
data = {my data }
headers = {'content-type': 'application/json'}
r = requests.post(url,data= json.dumps(data, headers=headers)
The issue come when my data is not one line but 500 lines of :
[
{
"Id" : "abc123",
"usr": "u1",
"pwd" : "p1"
},
{
"Id" : "abc124",
"usr": "u2",
"pwd" : "p2"
},
{
"Id" : "abc125",
"usr": "u3",
"pwd" : "p3"
}
.......
]
This really threw me off because "Id" field come from a random generater: id = gennum()
usr is from a query: usr = sqlout[0][0], and pwd is from pwd = sqlout[0][1].
I really do not have an idea how to read 500 line of data into my file data=....
I try to use data.append but do not know how to continue after that.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[update] sorry that question is not specific. my data comes from three different area:
(1) id row come from an random number generator: gennum()
(2) from query my database. sqlout variable will have 500 lines of out put wiht :
user, and pwd. so basically user = sqlout[0][0], and pwd will = sqlout[0][1] and they need to be in the post request body all together, in one request. so when I send the post request, my request bodywill contain 500 entries of json data like stated below. Hope this will clean the question up a little bit.
Read content of the file using open and file.read:
with open('/path/to/json_file') as f:
data = f.read()
url = 'http://mysurl.org'
headers = {'content-type': 'application/json'}
r = requests.post(url, data=data, headers=headers)
UPDATE after reading comments.
You can make dictionaries from multiple data sources using zip and list comprehension:
data = [{'id': id, 'usr': usr, 'pwd': pwd} for id,usr,pwd in
zip(id_data_generator, usr_data_generator, pwd_data_generator)]

Categories

Resources