如何使用Python从URL解析SVG文档(获取多段线的点)

2024-03-29 08:02:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一个Python扩展来解析来自<polyline>元素的SVG“points”值并打印它们?可能是从URL解析的?或者我可以保存SVG并在本地执行。你知道吗

我只需要它来解析points值,并为每个polyline元素分别打印它们。因此它将为当前<polyline>元素的每个points值打印这样的内容。你知道吗

[[239,274],[239,274],[239,274],[239,275],[239,275],[238,276],[238,276],[237,276],[237,276],[236,276],[236,276],[236,277] [236,277],[235,277],[235,277],[234,278],[234,278],[233,279],[233,279],[232,280] [232,280],[231,280],[231,280],[230,280],[230,280],[230,280],[229,280],[229,280]]

因此,在第一个polyline元素被解析和打印之后,它将解析下一个polyline元素并获取points的值,然后像第一个一样打印它,直到没有更多的元素要打印。你知道吗

SVG的URL:http://colorillo.com/bx0l.inline.svg

下面是SVG中多段线元素的HTML示例

<polyline points="239,274 239,274 239,274 239,275 239,275 238,276 238,276 237,276 237,276 236,276 236,276 236,277 236,277 235,277 235,277 234,278 234,278 233,279 233,279 232,280 232,280 231,280 231,280 230,280 230,280 230,280 229,280 229,280" style="fill: none; stroke: #000000; stroke-width: 1; stroke-linejoin: round; stroke-linecap: round; stroke-antialiasing: false; stroke-antialias: 0; opacity: 0.8"/>

我只是想寻求一些快速的帮助,还有一个例子。。如果你能帮我,那就太好了。你知道吗


Tags: svgcomhttpurl元素内容strokehtml
2条回答

下面

import xml.etree.ElementTree as ET
from collections import namedtuple
import requests
import re

Point = namedtuple('Point', 'x y')

all_points = []
r = requests.get('http://colorillo.com/bx0l.inline.svg')
if r.status_code == 200:
    data = re.sub(' xmlns="[^"]+"', '', r.content.decode('utf-8'), count=1)
    root = ET.fromstring(data)
    poly_lines = root.findall('.//polyline')
    for poly_line in poly_lines:
        tmp = []
        _points = poly_line.attrib['points'].split(' ')
        for _p in _points:
            tmp.append(Point(*[int(z) for z in _p.split(',')]))
        all_points.append(tmp)

for points in all_points:
    tmp = [str([p.x, p.y]).replace(' ','') for p in points]
    line = ','.join(tmp)
    print('[' + line + ']')

我相信某个地方有一个HTML提取包,但这就是我用核心python和正则表达式模块所要完成的任务。让txt成为您呈现的文本<polyline...,因此:

导入正则表达式模块

In [22]: import re

执行搜索:

In [24]: g = re.search('polyline points="(.*?)"', txt)

在上面的正则表达式中,我使用polyline points="作为锚点(我省略了<,因为它在正则表达式中有一个含义),并捕获所有剩余的部分,直到下一个引号。你知道吗

您想要的文本是通过以下方式实现的:

In [25]: g.group(1)
Out[25]: '239,274 239,274 239,274 239,275 239,275 238,276 238,276 237,276 237,276 236,276 236,276 236,277 236,277 235,277 235,277 234,278 234,278 233,279 233,279 232,280 232,280 231,280 231,280 230,280 230,280 230,280 229,280 229,280'

更新

使用xml来解析数据更安全,这里有一种方法(xml.etree文件包含在标准库中):

In [32]: import xml.etree.ElementTree as ET
In [33]: root = ET.fromstring(txt)

由于数据已格式化为根标记,因此不需要进一步提取:

In [35]: root.tag
Out[35]: 'polyline'

所有属性实际上都是XML属性,转换成字典:

In [37]: root.attrib
Out[37]:
{'points': '239,274 239,274 239,274 239,275 239,275 238,276 238,276 237,276 237,276 236,276 236,276 236,277 236,277 235,277 235,277 234,278 234,278 233,279 233,279 232,280 232,280 231,280 231,280 230,280 230,280 230,280 229,280 229,280', 'style': 'fill: none; stroke: #000000; stroke-width: 1; stroke-linejoin: round; stroke-linecap: round; stroke-antialiasing: false; stroke-antialias: 0; opacity: 0.8'}

所以这里有:

In [38]: root.attrib['points']
Out[38]: '239,274 239,274 239,274 239,275 239,275 238,276 238,276 237,276 237,276 236,276 236,276 236,277 236,277 235,277 235,277 234,278 234,278 233,279 233,279 232,280 232,280 231,280 231,280 230,280 230,280 230,280 229,280 229,280'

如果您想进一步根据逗号和空格将其拆分为多个组,我将执行以下操作:

使用不带参数的split获取由空格分隔的所有组:

>>> p = g.group(1).split()
>>> p
['239,274', '239,274', '239,274', '239,275', '239,275', '238,276', '238,276', '237,276', '237,276', '236,276', '236,276', '236,277', '236,277', '235,277', '235,277', '234,278', '234,278', '233,279', '233,279', '232,280', '232,280', '231,280', '231,280', '230,280', '230,280', '230,280', '229,280', '229,280']

现在,对于每个字符串,在返回字符串列表的逗号处拆分它。我使用map将每个这样的列表转换为int的列表:

>>> p2 = [list(map(int, numbers.split(','))) for numbers in p]
>>> p2
[[239, 274], [239, 274], [239, 274], [239, 275], [239, 275], [238, 276], [238, 276], [237, 276], [237, 276], [236, 276], [236, 276], [236, 277], [236, 277], [235, 277], [235, 277], [234, 278], [234, 278], [233, 279], [233, 279], [232, 280], [232, 280], [231, 280], [231, 280], [230, 280], [230, 280], [230, 280], [229, 280], [229, 280]]

这会给我们带来更多的启示:

>>> '123,456'.split(',')
['123', '456']
>>> list(map(int, '123,456'.split(',')))
[123, 456]

相关问题 更多 >