我正在使用urllib发出请求并获取一些返回的数据:
<base href="/project/example/" />
直到这里我都不会遇到任何问题:
queryURL = "https://hazards.fema.gov/gis/nfhl/rest/services/CSLF/Prelim_CSLF/MapServer/3/query"
params = urllib.parse.urlencode({'f': 'json', 'geometryType': 'esriGeometryPolygon', 'outFields': 'OBJECTID, SHAPE, CSLF_ID, Area_SF', 'returnGeometry': 'false'})
然后:
req = urllib.request.urlretrieve(queryURL, params)
在这一点上,我抛出一个错误-urllib.request.urlopen(req)
,我知道由于我格式化AttributeError: 'tuple' object has no attribute 'timeout'.
变量的方式,它返回了一个不变的元组。我的问题是,如何解决这个问题,以便可以开始查看结果?
params
根据要求,这是回溯:
jsonResult = json.load(response)
答案 0 :(得分:1)
核心问题是这段代码没有任何意义:
req = urllib.request.urlretrieve(queryURL, params)
urllib.request.urlopen(req)
urlretrieve
为您发出网络请求,将结果保存在本地文件中,然后返回“元组(filename, headers)
”。
您正在尝试将那对(filename, headers)
传递给urlopen
。但是urlopen
不知道该怎么办;它需要一个URL字符串或一个Request
对象,而一个(filename, headers)
对都不是。
此外,还不清楚您想要想要做什么。您已经获取了请求并将结果保存在文件中。您为什么要再次获取相同的请求?
简单的答案是,如果不想使用urlretrieve
。 (特别是因为它已被弃用……)只需执行以下操作:
response = urllib.request.urlopen(queryURL, params)
此外,请注意,我将urlopen
的结果保存在一个变量中。如果您不这样做,那么您只是在发出请求并丢弃响应,这不是很有用。并且jsonResult = json.load(response)
会给您一个NameError
,因为您从未创建任何名为response
的东西。
但是,您的代码仍然(至少)还有两个其他问题。
首先,正如urlencode
的文档所述:
如果将结果字符串用作POST的数据……则应将其编码为字节,否则将导致
TypeError
。
但是您没有那样做。
第二,如果要发送url编码的数据作为POST正文,则需要手动设置Content-Type
标头,这样。
即使您弄错了,某些服务器也会正确猜测,但这并不是您应该依靠的。
最后,如果您按照urllib.request
文档顶部的建议进行操作,那么所有这些操作将变得容易得多
另请参见:建议将Requests package用于更高级别的HTTP客户端界面。
有了请求,整个事情变成了:
queryURL = "https://hazards.fema.gov/gis/nfhl/rest/services/CSLF/Prelim_CSLF/MapServer/3/query"
params = {'f': 'json', 'geometryType': 'esriGeometryPolygon', 'outFields': 'OBJECTID, SHAPE, CSLF_ID, Area_SF', 'returnGeometry': 'false'}
jsonResult = requests.post(queryURL, data=params).json()