【发布时间】:2018-06-09 09:37:12
【问题描述】:
我正在尝试从 Appnexus api 请求批处理日志级别的数据。根据官方数据服务指南,主要有四个步骤:
1.帐户身份验证 -> 在 Json 中返回令牌
2。获取可用的数据源列表并查找下载参数 -> 在 Json 中返回参数
3.通过传递下载参数获取请求文件下载位置代码 -> 从标题中提取位置代码
4.通过位置码获取下载日志数据文件->返回gz数据文件
这些步骤在 Terminal 中使用 curl 完美运行:
curl -b cookies -c cookies -X POST -d @auth 'https://api.appnexus.com/auth'
curl -b cookies -c cookies 'https://api.appnexus.com/siphon?siphon_name=standard_feed'
curl --verbose -b cookies -c cookies 'https://api.appnexus.com/siphon-download?siphon_name=standard_feed&hour=2017_12_28_09×tamp=20171228111358&member_id=311&split_part=0'
curl -b cookies -c cookies 'http://data-api-gslb.adnxs.net/siphon-download/[location code]' > ./data_download/log_level_feed.gz
在 Python 中,我正在尝试同样的事情来测试 api。但是,它一直给我“ConnectionError”。在 steps 1-2 中,它仍然运行良好,因此我成功地从 Json 响应中获取了参数,以构建 step 3 的 url,我需要在其中请求位置代码并从响应的标头中提取它。
第一步:
# Step 1
############ Authentication ###########################
# Select End-Point
auth_endpoint = 'https://api.appnexus.com/auth'
# API Key
auth_app = json.dumps({'auth':{'username':'xxxxxxx','password':'xxxxxxx'}})
# Proxy
proxy = {'https':'https://proxy.xxxxxx.net:xxxxx'}
r = requests.post(auth_endpoint, proxies=proxy, data=auth_app)
data = json.loads(r.text)
token = data['response']['token']
第二步:
# Step 2
########### Check report list ###################################
check_list_endpoint = 'https://api.appnexus.com/siphon?siphon_name=standard_feed'
report_list = requests.get(check_list_endpoint, proxies=proxy, headers={"Authorization":token})
data = json.loads(report_list.text)
print(str(len(data['response']['siphons'])) + ' previous hours available for download')
# Build url for single report - extract para
download_endpoint = 'https://api.appnexus.com/siphon-download'
siphon_name = 'siphon_name=standard_feed'
hour = 'hour=' + data['response']['siphons'][400]['hour']
timestamp = 'timestamp=' + data['response']['siphons'][400]['timestamp']
member_id = 'member_id=311'
split_part = 'split_part=' + data['response']['siphons'][400]['splits'][0]['part']
# Build url
download_endpoint_url = download_endpoint + '?' + \
siphon_name + '&' + \
hour + '&' + \
timestamp + '&' + \
member_id + '&' + \
split_part
# Check
print(download_endpoint_url)
然而,以下步骤 3 中的“requests.get”并没有运行完成,而是不断发出“ConnectionError”警告。此外,我发现“位置代码”实际上是在警告信息中,就在“/siphon-download/”之后。所以,我使用“try..except”从警告消息中提取它并保持代码运行。
第三步:
# Step 3
######### Extract location code for target report ####################
try:
TT = requests.get(download_endpoint_url, proxies=proxy, headers={"Authorization":token}, timeout=1)
except ConnectionError, e:
text = e.args[0].args[0]
m = re.search('/siphon-download/(.+?) ', text)
if m:
location = m.group(1)
print('Successfully Extracting location: ' + location)
第 3 步中没有“try..except”的原始警告消息:
ConnectionError: HTTPConnectionPool(host='data-api-gslb.adnxs.net', port=80): Max retries exceeded with url:
/siphon-download/dbvjhadfaslkdfa346583
(Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x0000000007CBC7B8>:
Failed to establish a new connection: [Errno 10060] A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection failed because connected host has failed to respond',))
然后,我尝试使用从先前警告消息中提取的位置代码发出最后一个 GET 请求,以下载 gz 数据文件,就像我在终端中使用“curl”一样。但是,我收到了相同的警告消息 - ConnectionError。
第四步:
# Step 4
######## Download data file #######################
extraction_location = 'http://data-api-gslb.adnxs.net/siphon-download/' + location
LLD = requests.get(extraction_location, proxies=proxy, headers={"Authorization":token}, timeout=1)
Step4中的原始警告信息:
ConnectionError: HTTPConnectionPool(host='data-api-gslb.adnxs.net', port=80): Max retries exceeded with url:
/siphon-download/dbvjhadfaslkdfa346583
(Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x0000000007BE15C0>:
Failed to establish a new connection: [Errno 10060] A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection failed because connected host has failed to respond',))
为了仔细检查,我使用 curl 在终端中测试了我的 Python 脚本中生成的所有端点、参数和位置代码。它们都工作正常,下载的数据是正确的。任何人都可以帮助我在 Python 中解决这个问题,或者指出正确的方向来发现为什么会这样吗?非常感谢!
【问题讨论】:
-
为什么不用curl代理?
-
@feast 很抱歉造成混乱。是的,我也在 curl 中使用了代理。
-
如果设置 timeout=100 而不是 timeout=1 或强制 curl 1 秒超时会怎样?
-
因为服务器没有给你关于文件大小的信息。非阻塞下载需要额外的包通信,部分 Python 模块不支持。此外,服务器端所需的某些信息可能会丢失。从不获取数据并获取其中的某个部分是非常不同的。如果您将相同的文件放在本地服务器上并尝试下载它,它会引导您。
-
为什么在第 3 步中显示来自仅在第 4 步中引入的主机的
ConnectionError?
标签: python api curl python-requests urllib2