PythonBS4仅使用表头+另存为字典从wikipedia表中提取子表

2024-09-30 07:32:28 发布

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

我试图定义一个函数,它提取网站https://de.wikipedia.org/wiki/Stuttgart上“Basisdaten”表的所有行,并返回一个字典,其键和值对应于表中每行的第一个和第二个单元格。在

“Basisdaten”表是更大表的一部分,如以下代码的结果所示:

from bs4 import BeautifulSoup 
import requests
r=requests.get("https://de.wikipedia.org/wiki/Stuttgart")
soup=BeautifulSoup(r.text,"html.parser")
soup.find('th', text=re.compile('Basisdaten')).find_parent('table')

不幸的是,没有唯一的ID,我可以使用它来选择那些组成“Basisdaten”表的行。以下是我希望以HTML格式提取的行:

^{pr2}$

我成功地编写了这段代码,以字典形式给出了所需的结果:

data = []
def extractDict(y):
    results = y.find("th", {"colspan" : "2"}).find_parent('table').select('td')[3:35]
    for row in results:
        data.append(row.text.strip().replace('\xa0', '').replace(':', '').replace('[1]', ''))
    return dict(zip(data[::2], data[1::2]))
basisdaten=extractDict(soup)
basisdaten

结果

{'Adresse derStadtverwaltung': 'Marktplatz 170173 Stuttgart',
 'Bevölkerungsdichte': '3029Einwohner je km2',
 'Bundesland': 'Baden-Württemberg',
 'Einwohner': '628.032 (31.Dez.2016)',
 'Fläche': '207,35km2',
 'Gemeindeschlüssel': '08111000',
 'Höhe': '247m ü.NHN',
 'Kfz-Kennzeichen': 'S',
 'LOCODE': 'DE STR',
 'NUTS': 'DE111',
 'Oberbürgermeister': 'Fritz Kuhn (Bündnis 90/Die Grünen)',
 'Postleitzahlen': '70173–70619',
 'Regierungsbezirk': 'Stuttgart',
 'Stadtgliederung': '23 Stadtbezirkemit 152 Stadtteilen',
 'Vorwahl': '0711',
 'Webpräsenz': 'www.stuttgart.de'}

不过,我正在寻找一个更好的解决方案,它不需要简单地从父表中选择第4到35行。我随后打算在其他类似的wikipedia url上使用这段代码,“Basisdaten”表可能会因网站的行数而异。在

所有“Basisdaten”表之间的相似之处在于它们都嵌入在第一个表中,并且都有两列,因此都以“th colspan=”2“开头。父表包含其他子表,例如,在本例中,子表“Lage der Stadt Stuttgart in Baden-Württemberg”位于“Basisdaten”之后。在

是否可以编写一个循环来搜索“Basisdaten”子表头并获取其后的所有行,但在到达下一个子表头时停止(“th colspan=”2“)?在

我只找到了包含Basisdaten表开头的行:

soup.find('th', text=re.compile('Basisdaten'))

希望这有道理!我对beauthulsoup和Python非常陌生,这对我来说是一个非常具有挑战性的问题。在


Tags: 代码texthttpsorgdata网站defind
1条回答
网友
1楼 · 发布于 2024-09-30 07:32:28

这应该行

from bs4 import BeautifulSoup
import requests

data = requests.get("https://de.wikipedia.org/wiki/Stuttgart").text
soup = BeautifulSoup(data, "lxml")
trs = soup.select('table[id*="Infobox"] tr')
is_in_basisdaten = False
data = {}
clean_data = lambda x: x.get_text().strip().replace('\xa0', '').replace(':', '')
for tr in trs:
    if tr.th:
        if "Basisdaten" in tr.th.string:
                is_in_basisdaten = True
        if is_in_basisdaten and "Basisdaten" not in tr.th.string:
            break
    elif is_in_basisdaten:
        key, val = tr.select('td')
        data[clean_data(key)] = clean_data(val)

print(data)

相关问题 更多 >

    热门问题