Python中如何处理天天基金API返回的JS格式数据?
http://fundgz.1234567.com.cn/js/003095.js
例如这个基金,怎么使用不同键下边的键值?
Python中如何处理天天基金API返回的JS格式数据?
6 回复
这个应该是 JSONP 用的,你搜索一下看看爬虫怎么应对 JSONP 就好了,网上肯定有的
遇到天天基金API返回JS格式数据的情况,通常是因为数据被包装在JavaScript回调函数中(比如jsonpCallback(...))。处理这种数据的关键是提取出其中的JSON部分。
这里提供一个完整的解决方案:
import re
import json
import requests
def parse_js_callback_data(js_text):
"""
从JS回调函数中提取JSON数据
参数:
js_text: 包含JS回调函数的字符串,如 'jsonpCallback({...})'
返回:
解析后的Python字典
"""
# 方法1:使用正则表达式提取JSON部分
# 匹配花括号 {} 之间的内容,包括嵌套结构
pattern = r'\{.*\}'
match = re.search(pattern, js_text, re.DOTALL)
if match:
json_str = match.group()
try:
return json.loads(json_str)
except json.JSONDecodeError:
# 如果直接解析失败,尝试清理数据
return parse_js_callback_advanced(js_text)
return None
def parse_js_callback_advanced(js_text):
"""
更健壮的解析方法,处理各种JS格式
"""
# 移除函数调用包装
if '(' in js_text and ')' in js_text:
# 找到第一个 '(' 和最后一个 ')' 之间的内容
start = js_text.find('(') + 1
end = js_text.rfind(')')
json_str = js_text[start:end].strip()
# 清理可能的JavaScript注释和尾随分号
json_str = re.sub(r'//.*', '', json_str) # 移除单行注释
json_str = re.sub(r'/\*.*?\*/', '', json_str, flags=re.DOTALL) # 移除多行注释
json_str = json_str.rstrip(';') # 移除尾部分号
try:
return json.loads(json_str)
except json.JSONDecodeError as e:
print(f"JSON解析错误: {e}")
print(f"原始数据: {json_str[:200]}...") # 打印前200字符用于调试
return None
# 使用示例
def fetch_fund_data(fund_code):
"""
获取基金数据示例
"""
# 示例URL(实际URL需要替换)
url = f"https://fundgz.1234567.com.cn/js/{fund_code}.js"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.encoding = 'utf-8'
if response.status_code == 200:
# 解析JS格式数据
data = parse_js_callback_data(response.text)
return data
else:
print(f"请求失败,状态码: {response.status_code}")
return None
except requests.RequestException as e:
print(f"网络请求错误: {e}")
return None
# 测试代码
if __name__ == "__main__":
# 示例基金代码
fund_code = "110022" # 易方达消费行业
data = fetch_fund_data(fund_code)
if data:
print("解析成功!")
print(f"基金名称: {data.get('name', 'N/A')}")
print(f"当前净值: {data.get('dwjz', 'N/A')}")
print(f"估算涨幅: {data.get('gszzl', 'N/A')}%")
else:
print("数据获取或解析失败")
代码说明:
-
核心解析函数
parse_js_callback_data:- 使用正则表达式
r'\{.*\}'匹配花括号内的所有内容(包括嵌套) re.DOTALL标志让.匹配换行符,处理多行JSON
- 使用正则表达式
-
备用解析方法
parse_js_callback_advanced:- 通过查找
()来定位JSON数据 - 清理JavaScript注释和尾随分号
- 提供更健壮的解析
- 通过查找
-
实际应用
fetch_fund_data:- 模拟真实请求场景
- 添加合适的请求头(User-Agent)
- 处理网络异常
常见JS格式示例:
// 格式1:标准JSONP
jsonpCallback({"fundcode":"110022","name":"易方达消费行业"})
// 格式2:带分号
callback({"data": {...}});
// 格式3:带注释
/* 基金数据 */
getData({ "fund": {...} })
如果遇到特殊格式:
- 如果数据是
var data = {...}格式,可以搜索'='后的内容 - 如果包含特殊字符,可能需要先进行转义处理
- 某些API可能使用不同的回调函数名,需要相应调整
一句话总结:用正则或字符串切割提取JS回调中的JSON,再用json.loads解析。
其实就简单的去头去尾就可以了,然后当 json 来处理。因为在网页当中 JSONP 也是这么使用的,回调函数必须与约定的一致。最多也就最后有没有分号的差别。
jsonp 啊兄弟
JSONP 只是把 json 包装了一层 你把包装层去掉就行了
可以,明白了,已经完美解决。可惜的是为什么美人把它做成个库,直接调用就行。

