Python解析XML提取azimuthalGap并绘制直方图:代码返回空列表的优化求助
Python解析XML提取azimuthalGap并绘制直方图:代码返回空列表的优化求助
我有一份XML格式的ISC地震数据文件(示例片段见下文),写了一段Python脚本想要从中提取azimuthalGap的值,存入列表后绘制直方图,但目前运行代码后得到的gaps始终是空列表,希望能找到问题并优化代码。
我的代码目标是:
- a. 遍历XML文件,找到
<event>-><origin>-><quality>下的<azimuthalGap>节点 - b. 将每个
azimuthalGap的值存入gaps=[]变量 - c. 基于这些值绘制直方图
目前尝试的代码如下:
import xml.etree.ElementTree as ET def parse_azimuthal_gaps(xml_file): gaps = [] # Parse the XML file tree = ET.parse(xml_file) root = tree.getroot() # Iterate through each event for event in root.findall(".//event"): origin = event.find(".//origin") if origin is not None: # Find the azimuthal gap (if present) azimuthal_gap = origin.find(".//quality/azimuthalGap") if azimuthal_gap is not None: gap_value = azimuthal_gap.text if gap_value is not None: try: gaps.append(float(gap_value)) except ValueError: continue # Skip if not a valid float return gaps # Parse azimuthal gaps from the ISC XML file gaps = parse_azimuthal_gaps("SCB_earthquakes.xml") print("Azimuthal Gaps:", gaps[:10]) # Print the first 10 gaps for inspection
我的XML文件片段格式如下:
</event> <event publicID="smi:ISC/evid=602401243"> <preferredOriginID>smi:ISC/origid=601808754</preferredOriginID> <description> <text>Peru-Bolivia border region</text> <type>Flinn-Engdahl region</type> </description> <type>earthquake</type> <typeCertainty>known</typeCertainty> <comment> <text>Event reviewed by the ISC</text> </comment> <creationInfo> <agencyID>ISC</agencyID> <author>ISC</author> </creationInfo> <origin publicID="smi:ISC/origid=601808754"> <time> <value>2011-01-23T09:13:37.30Z</value> <uncertainty>0.96</uncertainty> </time> <latitude> <value>-11.9240</value> </latitude> <longitude> <value>-68.9133</value> </longitude> <depth> <value>58000.0</value> </depth> <depthType>operator assigned</depthType> <quality> <usedPhaseCount>8</usedPhaseCount> <associatedStationCount>6</associatedStationCount> <standardError>0.4800</standardError> <azimuthalGap>353.000</azimuthalGap> <minimumDistance>4.260</minimumDistance> <maximumDistance>5.070</maximumDistance> </quality> <creationInfo> <author>SCB</author> <agencyID>SCB</agencyID> </creationInfo> <originUncertainty> <preferredDescription>uncertainty ellipse</preferredDescription> <minHorizontalUncertainty>20399.9996185303</minHorizontalUncertainty> <maxHorizontalUncertainty>96000</maxHorizontalUncertainty> <azimuthMaxHorizontalUncertainty>83.0</azimuthMaxHorizontalUncertainty> </originUncertainty> <arrival publicID="smi:ISC/pickid=637614753/hypid=601808754"> <pickID>smi:ISC/pickid=637614753</pickID> <phase>Pn</phase> <azimuth>170.165</azimuth> <distance>4.404</distance> <timeResidual>3.6</timeResidual> </arrival> <arrival publicID="smi:ISC/pickid=637614754/hypid=601808754"> <pickID>smi:ISC/pickid=637614754</pickID> <phase>Sn</phase> <azimuth>170.165</azimuth> <distance>4.404</distance> <timeResidual>4.6</timeResidual> </arrival> </origin> <pick publicID="smi:ISC/pickid=637614753"> <time> <value>2011-01-23T09:14:46.10Z</value> </time> <waveformID networkCode="IR" stationCode="LPAZ"></waveformID> <onset>impulsive</onset> <polarity>positive</polarity> <phaseHint>Pn</phaseHint> </pick> <pick publicID="smi:ISC/pickid=637614754"> <time> <value>2011-01-23T09:15:37.60Z</value> </time> <waveformID networkCode="IR" stationCode="LPAZ"></waveformID> <onset>emergent</onset> <phaseHint>Sn</phaseHint> </pick> <magnitude publicID="smi:ISC/magid=602398394"> <mag> <value>3.80</value> <uncertainty>0.40</uncertainty> </mag> <type>Ml</type> <originID>smi:ISC/origid=601808754</originID> <stationCount>2</stationCount> <creationInfo> <author>SCB</author> </creationInfo> </magnitude> <preferredMagnitudeID>smi:ISC/magid=602398394</preferredMagnitudeID>
请问有没有办法优化这段代码,让它能正确提取到azimuthalGap的值?
问题排查与优化方案
看你的情况,大概率是XML命名空间在搞鬼——ISC的地震XML文件几乎都会带有命名空间声明(比如http://quakeml.org/xmlns/bed/1.2这类),而xml.etree.ElementTree默认不会处理命名空间,导致你的find/findall找不到对应节点。另外,递归查找//虽然能用,但精准定位层级会更可靠,也能避免误匹配深层节点。
优化后的完整代码(含命名空间处理+直方图绘制)
import xml.etree.ElementTree as ET import matplotlib.pyplot as plt def parse_azimuthal_gaps(xml_file): gaps = [] tree = ET.parse(xml_file) root = tree.getroot() # 自动提取XML命名空间(如果存在) namespace = "" if '}' in root.tag: # 从根节点标签中拆分出命名空间 namespace = root.tag.split('}')[0] + '}' # 如果自动提取有问题,也可以手动指定,比如: # namespace = "{http://quakeml.org/xmlns/bed/1.2}" # 精准层级查找:event -> origin -> quality -> azimuthalGap for event in root.findall(f".//{namespace}event"): # 找当前event下的直接origin子节点 origin = event.find(f"{namespace}origin") if origin is not None: # 找当前origin下的直接quality子节点 quality = origin.find(f"{namespace}quality") if quality is not None: azimuthal_gap = quality.find(f"{namespace}azimuthalGap") if azimuthal_gap is not None and azimuthal_gap.text is not None: try: # 去除文本前后空白后转成浮点数 gaps.append(float(azimuthal_gap.text.strip())) except ValueError: print(f"跳过无效的azimuthalGap值:{azimuthal_gap.text}") continue return gaps # 提取数据 gaps = parse_azimuthal_gaps("SCB_earthquakes.xml") # 处理结果并绘图 if gaps: print(f"共提取到{len(gaps)}个azimuthalGap值,前10个为:{gaps[:10]}") # 绘制直方图 plt.figure(figsize=(10,6)) plt.hist(gaps, bins=20, edgecolor='black', alpha=0.7) plt.title('Azimuthal Gap 分布直方图') plt.xlabel('Azimuthal Gap 值') plt.ylabel('数据数量') plt.grid(axis='y', linestyle='--', alpha=0.7) plt.show() else: print("未提取到任何azimuthalGap值,请检查:") print("1. XML文件路径是否正确") print("2. XML节点结构是否与预期一致") print("3. 命名空间是否需要手动指定")
关键优化说明:
- 命名空间自动适配:代码会自动识别XML的命名空间,不用手动硬编码,适配大多数ISC地震XML文件。
- 精准节点定位:把递归查找改成直接子节点查找,减少无效遍历,避免匹配到错误层级的节点。
- 增加异常提示:遇到非数值的无效值时会打印提示,方便你排查数据问题。
- 整合绘图逻辑:直接把直方图绘制功能加了进去,提取到数据后自动生成可视化图表。
另外,记得确认SCB_earthquakes.xml和脚本在同一目录下,或者使用绝对路径指定文件位置哦。
备注:内容来源于stack exchange,提问作者tonino
相关产品推荐
相关产品推荐

