我获得了从XML(内部网络,出于安全原因无法提供URL)提取数据的功能:
" & ' < > £
我希望此函数在包含def crawl_and_get_data(url, keys, param1, param2, param3):
r = requests.get(url, auth = HTTPDigestAuth(keys[0], keys[1]))
xml_url = 'http://www.sitetogetdata.com/xml/?param1=' + param1 + '¶m2=' + param2 + '¶m3=' + param3
res = requests.get(xml_url, auth = HTTPDigestAuth(keys[0], keys[1]))
xml = res.text
return xml
,param1
和param2
的循环中工作。
param3
在大多数情况下,它可以工作,但在某些特定情况下,它不能工作。执行完后,我尝试再次获取数据,但不在循环内,并且可以正常工作。
frames = []
for i in range(len(table_with_params)):
try:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
data = crawl_and_get_data(url, keys, param1, param2, param3)
frames.append(data)
except TypeError:
print('Whoops, something is wrong with this request.')
continue
有任何暗示吗?预先感谢。
编辑:跳过异常处理,返回的错误是:
data = crawl_and_get_data(url, keys, problematic_param1, problematic_param2, problematic_param3)
# it works!
该函数在循环外运行时不会引发此错误。
答案 0 :(得分:2)
HTTP请求失败的原因有很多,它们有时会成功,这是一个奇迹,因此您最好为失败的请求做好准备。话虽这么说,您的问题实际上可能完全在其他地方,并且您的(相当糟糕的)异常处理使您无法获得任何提示。
您的第一个问题是try块太大,您想将try块限制为严格必要的范围。第二个问题是您完全忽略了实际的异常,仅打印了一条完全无用的消息。
当前,您在try块中主要包含三个不同的部分:准备请求的参数,执行请求本身(实际上是2个请求)以及对结果进行处理。这些部分中的每个部分都可以引发自己的特定异常,因此适当的异常处理方案是将每个部分放在不同的try块中(或者,如果您不希望有什么特别的事情,则至少在其他try块之外)–结果”部分仅是frames.append(data)
,则实际上并不能保证使用try / except块)。 IOW,您想要这样的东西:
try:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
except TypeError as e:
print("invalid source value at row {} : {}".format(i, e))
continue
try:
data = crawl_and_get_data(url, keys, param1, param2, param3)
您在这里不应该出现任何TypeError-从理论上讲,即是什么,可能是您真正的问题所在
except RequestError as e:
print("Failed request for row {} : {}".format(i, e))
continue
frames.append(data)
请注意,使用logging
模块会更好,特别是因为它知道如何正确记录完整的错误回溯(通常包含非常有价值的调试信息)。
还请注意:
def crawl_and_get_data(url, keys, param1, param2, param3):
r = requests.get(url, auth = HTTPDigestAuth(keys[0], keys[1]))
如果目标是登录并且url在外部(调用)循环中是恒定的,则您可能需要have a look at requests sessions instead,这可以将查询数量减半。否则,这对您和目标服务器来说都是浪费时间,带宽和CPU周期。请对服务器的所有者好一些。
xml_url = 'http://www.sitetogetdata.com/xml/?param1=' + param1 + '¶m2=' + param2 + '¶m3=' + param3
res = requests.get(xml_url, auth = HTTPDigestAuth(keys[0], keys[1]))
现在这里是TypeError
的来源(假设您发布的内容是您的真实代码或足够类似的代码):您将调用者代码中的params值显式转换为int
,现在尝试用字符串连接这些整数。这是行不通的,确实会引发TypeError
(出于很好的原因-默默地转换不兼容类型的语言被设计破坏了)。
通常,对于此类操作,您最好使用字符串格式而不是字符串连接,即:
xml_url = '...?param1={}¶m2={}¶m3={}'.format(param1, param2, param3)
不仅可读性强,而且会调用str()
(或取决于格式说明符的适当格式函数),避免使用TypeError
。
但是HTTP查询字符串和python-requests
already knows how to properly create a valid querystring from a dict还有其他陷阱,因此您实际上应该使用:
res = requests.get(url, params={"param1": param1, "param2": param2, "param3": param3}, ....)
答案 1 :(得分:0)
错误不是来自爬网。它在以下几行中:
param1 = int(table_with_params.loc[i, 'param1'])
param2 = int(table_with_params.loc[i, 'param2'])
param3 = int(table_with_params.loc[i, 'param3'])
其中一行返回一个不能转换为int的pandas Series对象。 请原谅我的格式设置,因为我是stackoverflow的新手,也不知道如何正确设置代码格式。
谢谢