前言
碰到一个特殊类型的网站,石河子镇人民政府 ,外观看起来很正常(丑不算不正常),但是打开源码,发现只有XML格式的数据。大致看了一下页面源码,发现和页面展示相关的文件引用结构是这样的:
HomePage (XML) ---+ (看到的页面)
|
index.xsl ---+ (主样式表)
|
system_entity.xsl (主样式表中导入的样式表 * 2)
turnpage.xsl
如果使用XSLT
根据样式表xsl对XML数据进行转换,需要将全部样式表导入同一命名空间,但是暂时没找到好的处理办法,于是使用最low的方法,将全部xsl样式表合并为一个文本文档。值得注意的是:合并的时候,子文档的声明和根级标签都不能存在。
基本概念
基本步骤
- 获取HomePage的XML源码
- 根据HomePage的xsl链接,获取index.xsl源码
- 根据index.xsl中的导入样式表链接,获取导入的样式表源码
- 将多个导入的子样式表,移除声明和root标签,替换到index.xsl对应的导入行
- 使用
lxml.etree.XML()
分别将XML和XSL文档转换为XML_dom
和XSL_dom
- 使用
lxml.etree.XSLT()
将XSL_dom
转换为XSLT实例(这是一个callable对象,暂且将它命名为transform
) - 通过调用
transform(XSL_dom)
获得result
,数据类型为lxml.etree._XSLTResultTree
- 可已直接将
result
写入文件或者通过str(result)
转换为字符串,得到的字符串就是最终的HTML源码
使用Python
lxml.etree.XSLT
进行转换
上示例面条代码
import re
import urlparse
from lxml import etree
import requests
url = "http://shzz.shz.gov.cn/structure/index"
# 下载XML页面
xml_response = requests.get(url)
xml_response.encoding = "utf-8"
xml_source = xml_response.text
# 将XML转换为dom树
xml_dom = etree.XML(xml_response.content)
# 获取index.xsl的url
index_xsl_href = re.compile(r"<\?xml-stylesheet.*?href=\"(.*?)\"\?>").findall(xml_source)[0]
index_xsl_url = urlparse.urljoin(url, index_xsl_href)
# 下载index.xls源码
index_xsl_resp = requests.get(index_xsl_url)
index_xsl_resp.encoding = "utf-8"
index_xsl_dom = etree.XML(index_xsl_resp.content)
index_xsl_source = etree.tostring(index_xsl_dom, encoding="unicode", method="xml")
# 获得import turnpage.xsl源码
system_entity_href, turnpage_href = re.compile(r"<xsl:import href=\"(.*?)\"").findall(index_xsl_source)
turnpage_url = urlparse.urljoin(url, turnpage_href)
turnpage_resp = requests.get(turnpage_url)
# 去除声明,同时也是为了单独确认文档结构在转换为dom树是不会引起异常
turnpage_xsl_dom = etree.XML(turnpage_resp.content)
turnpage_xsl_source = etree.tostring(turnpage_xsl_dom, encoding="unicode", method="xml")
# 获取import system_entity.xsl 源码
system_entity_url = urlparse.urljoin(url, system_entity_href)
system_entity_resp = requests.get(system_entity_url)
# 去除声明,同上
system_entity_dom = etree.XML(system_entity_resp.content)
system_entity_source = etree.tostring(system_entity_dom, encoding="unicode", method="xml")
# 移除两个导入样式表的根级标签
turnpage_xsl_source = re.compile(r"</?xsl:stylesheet.*?>").sub("", turnpage_xsl_source)
system_entity_source = re.compile(r"</?xsl:stylesheet.*?>").sub("", system_entity_source)
# 将两个无根标签的样式表源码,替换到index.xsl的对应导入位置
integrated_xsl_source = re.compile(r'(?u)<xsl:import href="/cws.files/component/common/template/turnpage.xsl"/>').sub(turnpage_xsl_source, index_xsl_source)
integrated_xsl_source = re.compile(r'(?u)<xsl:import href="/cws.files/component/common/template/system_entity.xsl"/>').sub(system_entity_source, integrated_xsl_source)
# 获得transform
xsl_dom = etree.XML(integrated_xsl_source)
transform = etree.XSLT(xsl_dom)
# 最终转换为HTML,打印出结果
new_xml_result = transform(xml_dom)
print(new_xml_result)
第一次处理这样的问题,还有很多不太理解的地方,欢迎大家指导、指正。