簡體   English   中英

美麗的湯-`findAll`不能捕獲SVG中的所有標簽(`ElementTree`可以)

[英]Beautiful Soup - `findAll` not capturing all tags in SVG (`ElementTree` does)

我正在嘗試通過修改描述美國所有縣的SVG地圖來生成Choropleth地圖。 基本方法由Flowing Data捕獲。 由於SVG基本上只是XML,因此該方法利用了BeautifulSoup解析器。

問題是,解析器無法捕獲SVG文件中的所有path元素。 以下僅捕獲了149條路徑(超過3000條路徑):

#Open SVG file
svg=open(shp_dir+'USA_Counties_with_FIPS_and_names.svg','r').read()

#Parse SVG
soup = BeautifulSoup(svg, selfClosingTags=['defs','sodipodi:namedview'])

#Identify counties
paths = soup.findAll('path')

len(paths)

但是,我知道物理檢查和ElementTree方法使用以下例程捕獲3,143條路徑的事實都存在很多:

#Parse SVG
tree = ET.parse(shp_dir+'USA_Counties_with_FIPS_and_names.svg')

#Capture element
root = tree.getroot()

#Compile list of IDs from file
ids=[]
for child in root:
    if 'path' in child.tag:
        ids.append(child.attrib['id'])

len(ids)

我還沒有弄清楚如何以一種尚未完全弄亂的方式從ElementTree對象進行寫入。

#Define style template string
style='font-size:12px;fill-rule:nonzero;stroke:#FFFFFF;stroke-opacity:1;'+\
        'stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;'+\
        'stroke-linecap:butt;marker-start:none;stroke-linejoin:bevel;fill:'

#For each path...
for child in root:
    #...if it is a path....
    if 'path' in child.tag:
        try:
            #...update the style to the new string with a county-specific color...
            child.attrib['style']=style+col_map[child.attrib['id']]
        except:
            #...if it's not a county we have in the ACS, leave it alone
            child.attrib['style']=style+'#d0d0d0'+'\n'

#Write modified SVG to disk
tree.write(shp_dir+'mhv_by_cty.svg')

上面的修改/寫入例程會產生這種怪異現象:

各縣平均房屋價值中位數

我的主要問題是:為什么BeautifulSoup無法捕獲所有path標簽? 其次,為什么用ElementTree對象修改的圖像會進行所有此類課外活動? 任何建議將不勝感激。

您需要執行以下操作:

  • 升級到beautifulsoup4

     pip install beautifulsoup4 -U 
  • 導入為:

     from bs4 import BeautifulSoup 
  • 安裝最新的lxml模塊:

     pip install lxml -U 
  • 明確指定lxml作為解析器:

     soup = BeautifulSoup(svg, 'lxml') 

演示:

>>> from bs4 import BeautifulSoup
>>> 
>>> svg = open('USA_Counties_with_FIPS_and_names.svg','r').read()
>>> soup = BeautifulSoup(svg, 'lxml')
>>> paths = soup.findAll('path')
>>> len(paths)
3143

亞歷克斯的答案對您的第一個問題是正確的。 關於第二個問題:

為什么用ElementTree對象修改的圖像會進行所有這些課外活動?

答案很簡單-並非每個<path>元素都畫一個縣。 具體來說,應該刪除兩個元素,一個具有id="State_Lines" ,另一個具有id="separator" 您沒有提供顏色數據集,所以我只為每個縣使用了一個隨機的十六進制顏色生成器(從此處改編),然后使用lxml解析.svg的XML並遍歷每個<path>元素,跳過了我上面提到的那些:

from lxml import etree as ET
import random

def random_color():
    r = lambda: random.randint(0,255)
    return '#%02X%02X%02X' % (r(),r(),r())

new_style = 'font-size:12px;fill-rule:nonzero;stroke:#FFFFFF;stroke-opacity:1;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:butt;marker-start:none;stroke-linejoin:bevel;fill:'

tree = ET.parse('USA_Counties_with_FIPS_and_names.svg')
root = tree.getroot()
for child in root:
    if 'path' in child.tag and child.attrib['id'] not in ["separator", "State_Lines"]:
        child.attrib['style'] = new_style + random_color()

tree.write('counties_new.svg')

產生了這個漂亮的圖像:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM