'bytes' object has no attribute 'items' - python

While doing a CTF challenge, we are asked to enter MD5 hash of a certain 'key' within few milliseconds, so I'm trying to automate the task like this in Python3:
import re
import urllib.request
import urllib.parse
import hashlib
url = 'http://random.page'
page = urllib.request.urlopen(url)
header = {}
header['Set-Cookie'] = page.info()['Set-Cookie']
html = page.read().decode('utf-8')
key = re.search("<h3 align='center'>+.*</h3>", html).group(0)[19:-5]
md5 = hashlib.md5(key.encode()).hexdigest()
data = {'hash':md5}
post_data = urllib.parse.urlencode(data).encode('ascii')
post_header = urllib.parse.urlencode(header).encode('ascii')
request = urllib.request.Request(url, data=post_data, headers=post_header)
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
I want the same session as the 'key' gets changed at every request, so I'm trying to use the same cookie. But this error arises:
Traceback (most recent call last):
File "MD5.py", line 18, in <module>
request = urllib.request.Request(url, data=post_data, headers=post_header)
File "/usr/lib/python3.7/urllib/request.py", line 334, in __init__
for key, value in headers.items():
AttributeError: 'bytes' object has no attribute 'items'

Do not urlencode headers. urllib.request.Request expects it to be a dictionary.
Simply pass the headers as is and it will fix your problem.

Related

Get Value Of API Dictionary

I'm using a service with an API key and I want to print my balance.
from requests_html import HTMLSession
session = HTMLSession()
r = session.post('https://api.anycaptcha.com/getBalance', data = {'clientKey': API})
Everything works. When I do print(r.text) the following dictionary gets print:
{"errorId":0,"errorCode":"SUCCESS","balance":20.0}
However, I just want to get the value of "balance" (20.0). But I couldn't figure out how.
What I tried:
print(r.text['balance'])
# Output:
Traceback (most recent call last):
File "X/test.py", line 7, in <module>
print(r.text['balance'])
TypeError: string indices must be integers
Try this, as r.text is a string with your dict
import json
d = json.loads(r.text)
#Now you can access dict
d["balance"]

NameError in function to retrieve JSON data

I'm using python 3.6.1 and have the following code which successfully retrieves data in JSON format:
import urllib.request,json,pprint
url = "https://someurl"
response = urllib.request.urlopen(url)
data = json.loads(response.read())
pprint.pprint(data)
I want to wrap this in a function, so i can reuse it. This is what i have tried in a file called getdata.py:
from urllib.request import urlopen
import json
def get_json_data(url):
response = urlopen(url)
return json.loads(response.read())
and this is the error i get after importing the file and attempting to print out the response:
>>> import getdata
>>> print(getdata.get_json_data("https://someurl"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Nick\getdata.py", line 6, in get_json_data
from urllib.request import urlopen
NameError: name 'urllib' is not defined
i also tried this and got the same error:
import urllib.request,json
def get_json_data(url):
response = urllib.request.urlopen(url)
return json.loads(response.read())
What do i need to do to get this to work please?
cheers
Its working now ! I think the problem was the hydrogen addon i have for the Atom editor. I uninstalled it, tried again and it worked. Thanks for looking.

typeerror 'bytes' object is not callable

My code:
import psycopg2
import requests
from urllib.request import urlopen
import urllib.parse
uname = " **** "
pwd = " ***** "
resp = requests.get("https://api.flipkart.net/sellers/skus/SKUID/listings", auth=(uname, pwd))
con_page = resp.content()
print (con_page)
I am getting this error:
Traceback (most recent call last):
File "C:\Users\Prime\Documents\NetBeansProjects\Fp_API\src\fp_api.py", line 18, in <module>
con_page = resp.content()
TypeError: 'bytes' object is not callable
Based on the documentation, the return value of requests.get() is a requests.Response, which has a content field with the type bytes, rather than a content() method.
Try this instead:
con_page = resp.content
do this:
con_page = resp.content.decode()

Python-ldap ldap.initialize rejects a URL that ldapurl considers valid

I want to open a connection to a ldap directory using ldap url that will be given at run time. For example :
ldap://192.168.2.151/dc=directory,dc=example,dc=com
It is valid as far as I can tell. Python-ldap url parser ldapurl.LDAPUrl accepts it.
url = 'ldap://192.168.2.151/dc=directory,dc=example,dc=com'
parsed_url = ldapurl.LDAPUrl(url)
parsed_url.dn
'dc=directory,dc=example,dc=com'
But if I use it to initialize a LDAPObject, I get a ldap.LDAPError exception
ldap.initialize(url)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/ldap/functions.py", line 91, in initialize
return LDAPObject(uri,trace_level,trace_file,trace_stack_limit)
File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 70, in __init__
self._l = ldap.functions._ldap_function_call(ldap._ldap_module_lock,_ldap.initialize,uri)
File "/usr/lib/python2.7/dist-packages/ldap/functions.py", line 63, in _ldap_function_call
result = func(*args,**kwargs)
ldap.LDAPError: (0, 'Error')
I found that if I manually encode the dn part of the url, it works :
url = 'ldap://192.168.2.151/dc=directory%2cdc=example%2cdc=com'
#url still valid
parsed_url = ldapurl.LDAPUrl(url)
parsed_url.dn
'dc=directory,dc=example,dc=com'
#and will return a valid connection
ldap.initialize(url)
<ldap.ldapobject.SimpleLDAPObject instance at 0x1400098>
How can I ensure robust url handling in ldap.initialize without encoding parts of the url myself ? (which, I'm afraid, won't be that robust anyway).
You can programatically encode the last part of the URL:
from urllib import quote # works in Python 2.x
from urllib.parse import quote # works in Python 3.x
url = 'ldap://192.168.2.151/dc=directory,dc=paralint,dc=com'
idx = url.rindex('/') + 1
url[:idx] + quote(url[idx:], '=')
=> 'ldap://192.168.2.151/dc=directory%2Cdc=paralint%2Cdc=com'
One can use LDAPUrl.unparse() method to get a properly encoded version of the URI, like this :
>>> import ldapurl
>>> url = ldapurl.LDAPUrl('ldap://192.168.2.151/dc=directory,dc=example,dc=com')
>>> url.unparse()
'ldap://192.168.2.151/dc%3Ddirectory%2Cdc%3Dparalint%2Cdc%3Dcom???'
>>> ldap.initialize(url.unparse())
<ldap.ldapobject.SimpleLDAPObject instance at 0x103d998>
And LDAPUrl.unparse() will not reencode an already encoded url :
>>> url = ldapurl.LDAPUrl('ldap://example.com/dc%3Dusers%2Cdc%3Dexample%2Cdc%3Dcom%2F???')
>>> url.unparse()
'ldap://example.com/dc%3Dusers%2Cdc%3Dexample%2Cdc%3Dcom%2F???'
So you can use it blindly on any ldap uri your program must handle.

Nonetype object has no attribute '__getitem__'

I am trying to use an API wrapper downloaded from the net to get results from the new azure Bing API. I'm trying to implement it as per the instructions but getting the runtime error:
Traceback (most recent call last):
File "bingwrapper.py", line 4, in <module>
bingsearch.request("affirmative action")
File "/usr/local/lib/python2.7/dist-packages/bingsearch-0.1-py2.7.egg/bingsearch.py", line 8, in request
return r.json['d']['results']
TypeError: 'NoneType' object has no attribute '__getitem__'
This is the wrapper code:
import requests
URL = 'https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/Web?Query=%(query)s&$top=50&$format=json'
API_KEY = 'SECRET_API_KEY'
def request(query, **params):
r = requests.get(URL % {'query': query}, auth=('', API_KEY))
return r.json['d']['results']
The instructions are:
>>> import bingsearch
>>> bingsearch.API_KEY='Your-Api-Key-Here'
>>> r = bingsearch.request("Python Software Foundation")
>>> r.status_code
200
>>> r[0]['Description']
u'Python Software Foundation Home Page. The mission of the Python Software Foundation is to promote, protect, and advance the Python programming language, and to ...'
>>> r[0]['Url']
u'http://www.python.org/psf/
This is my code that uses the wrapper (as per the instructions):
import bingsearch
bingsearch.API_KEY='abcdefghijklmnopqrstuv'
r = bingsearch.request("affirmative+action")
I tested this out myself, and it seems what you are missing is to properly url-encode your query. Without it, I was getting a 400 code.
import urllib2
import requests
# note the single quotes surrounding the query
URL = "https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/Web?Query='%(query)s'&$top=50&$format=json"
query = 'affirmative+action'
# query == 'affirmative%2Baction'
r = requests.get(URL % {'query': urllib2.quote(query)}, auth=('', API_KEY))
print r.json['d']['results']
Your example doesn't make much sense because your request wrapper returns a list of results, yet in your main usage example you are calling it and then checking a status_code attribute on the return value (which is the list). That attribute would be present on the response objects, but you don't return it from your wrapper.

Categories