в настоящее время я пытаюсь применить подход bs4 к странице википедии: результаты не сохраняются в df
из-за того, что парсинг в Википедии является очень распространенным методом, при котором мы можем использовать подходящий подход для работы со многими разными заданиями, у меня были некоторые проблемы с возвратом результатов и сохранением их в df.
ну, в качестве примера очень распространенного задания Wikipedia-bs4, мы можем взять вот это:
на этой странице у нас есть более 600 результатов - на подстраницах: url = "https://de.wikipedia.org/wikiListe_der_St%C3%A4dte_in_Deutschland#Liste_der_St%C3%A4dte_in_Deutschland"
Итак, чтобы создать первый экспериментальный сценарий, я следую следующим образом: сначала я очищаю таблицу со страницы Википедии, а затем конвертирую ее в DataFrame Pandas. Поэтому я сначала устанавливаю необходимые пакеты: убедитесь, что у вас установлены запросы, beautifulsoup4 и pandas. Вы можете установить их с помощью pip, если вы еще этого не сделали:
Pip запрашивает установку beautifulsoup4 pandas
а затем я делаю следующее: сначала я очищаю таблицу со страницы Википедии, а затем конвертирую ее в DataFrame Pandas.
import pandas as pd
# URL of the Wikipedia page
url = "https://de.wikipedia.org/wiki/Liste_der_St%C3%A4dte_in_Deutschland#Liste_der_St%C3%A4dte_in_Deutschland"
table = pd.read_html(url, extract_links='all')[1]
base_url = 'https://de.wikipedia.org'
table = table.apply(lambda col: [v[0] if v[1] is None else f'{base_url}{v[1]}' for v in col])
links = list(table.iloc[:,0])
for link in links:
print('\n',link)
try:
df = pd.read_html(link)[0]
print(df)
except Exception as e:
print(e)
посмотрим, что я получу в ответ — всего две записи. вместо сотен. кстати; Я думаю, что лучший способ — собрать все в df. и &/или сохранить его
Document is empty
https://de.wikipedia.org/wiki/Aach_(Hegau)
Wappen \
0 NaN
1 NaN
2 Basisdaten
3 Koordinaten:
4 Bundesland:
5 Regierungsbezirk:
6 Landkreis:
7 Höhe:
8 Fläche:
9 Einwohner:
10 Bevölkerungsdichte:
11 Postleitzahl:
12 Vorwahl:
13 Kfz-Kennzeichen:
14 Gemeindeschlüssel:
15 LOCODE:
16 Adresse der Stadtverwaltung:
17 Website:
18 Bürgermeister:
19 Lage der Stadt Aach im Landkreis Konstanz
20 Karte
Deutschlandkarte
0 NaN
1 NaN
2 Basisdaten
3 47° 51′ N, 8° 51′ OKoordinaten: 47° 51′ N, 8° ...
4 Baden-Württemberg
5 Freiburg
6 Konstanz
7 545 m ü. NHN
8 10,68 km2
9 2384 (31. Dez. 2022)[1]
10 223 Einwohner je km2
11 78267
12 07774
13 KN, STO
14 08 3 35 001
15 DE AAC
16 Hauptstraße 16 78267 Aach
17 www.aach.de
18 Manfred Ossola
19 Lage der Stadt Aach im Landkreis Konstanz
20 Karte
примечание: у нас там несколько сотен записей:
см. информационное окно: я хочу получить данные информационного окна
обновление: на что направлено: - как получить полные результаты - которые хранятся в файле df. - и содержащий все данные - в поле info.. (см. изображение выше) - с контактной информацией и т. д.
обновление2:
обзор - страница: https://de.wikipedia.org/wiki/Liste_der_St%C3%A4dte_in_Deutschland#Liste_der_St%C3%A4dte_in_Deutschland
это приведет нас примерно к 1000 подстраницам: как показано ниже
Аах (Хегау): https://de.wikipedia.org/wiki/Aach_(Хегау) Ахен: https://de.wikipedia.org/wiki/Аахен Аален: https://de.wikipedia.org/wiki/Аален
увидеть результат так называемого «информационного окна»: https://de.wikipedia.org/wiki/Babenhausen_(Hessen) Бабенхаузен (Гессен)
+----------------------+--------------------------------------------------------------+
| | |
+----------------------+--------------------------------------------------------------+
| koordinaten: | ♁49° 58′ N, 8° 57′ OKoordinaten: 49° 58′ N, 8° 57′ O | | OSM |
| Bundesland: | Hessen |
| Regierungsbezirk: | Darmstadt |
| Landkreis: | Darmstadt-Dieburg |
| Höhe: | 124 m ü. NHN |
| Fläche: | 66,85 km2 |
| Einwohner: | 17.579 (31. Dez. 2023)[1] |
| Bevölkerungsdichte: | 263 Einwohner je km2 |
| Postleitzahl: | 64832 |
| Vorwahl: | 06073 |
| Kfz-Kennzeichen: | DA, DI |
| Gemeindeschlüssel: | 06 4 32 002 |
| Stadtgliederung: | 6 Stadtteile |
| Adresse der | |
| Stadtverwaltung: | Rathaus |
| Marktplatz 2 | |
| 64832 Babenhausen | |
| Website: | www.babenhausen.de |
| Bürgermeister: | Dominik Stadler (parteilos) |
+----------------------+--------------------------------------------------------------+
https://de.wikipedia.org/wiki/Bacharachhttps://de.wikipedia.org/wiki/Backnang
update3: если я запустил этот код, чтобы получить 300 записей. это работает хорошо - если я запущу это, чтобы получить 2400, это не удастся..
import requests
from bs4 import BeautifulSoup
import pandas as pd
def get_info(city_url: str) -> dict:
info_data = {}
response = requests.get(city_url)
soup = BeautifulSoup(response.text, 'lxml')
for x in soup.find('tbody').find_all(
lambda tag: tag.name == 'tr' and tag.get('class') == ['hintergrundfarbe-basis']):
if not x.get('style'):
if 'Koordinaten' in x.get_text():
info_data['Koordinaten'] = x.findNext('span', class_='coordinates').get_text()
else:
info_data[x.get_text(strip=True).split(':')[0]] = x.get_text(strip=True).split(':')[-1]
info_data['Web site'] = soup.find('a', {'title':'Website'}).findNext('a').get('href')
return info_data
cities = []
response = requests.get('https://de.wikipedia.org/wiki/Liste_der_St%C3%A4dte_in_Deutschland#Liste_der_St%C3%A4dte_in_Deutschland')
soup = BeautifulSoup(response.text, 'lxml')
for city in soup.find_all('dd')#[:2500]:
city_url = 'https://de.wikipedia.org' + city.findNext('a').get('href')
result = {'City': city.get_text(), 'URL': 'https://de.wikipedia.org' + city.findNext('a').get('href')}
result |= get_info(city_url)
cities.append(result)
df = pd.DataFrame(cities)
print(df.to_string())
------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-28-4391c852fd75> in <cell line: 24>()
25 city_url = 'https://de.wikipedia.org' + city.findNext('a').get('href')
26 result = {'City': city.get_text(), 'URL': 'https://de.wikipedia.org' + city.findNext('a').get('href')}
---> 27 result |= get_info(city_url)
28 cities.append(result)
29 df = pd.DataFrame(cities)
<ipython-input-28-4391c852fd75> in get_info(city_url)
15 else:
16 info_data[x.get_text(strip=True).split(':')[0]] = x.get_text(strip=True).split(':')[-1]
---> 17 info_data['Web site'] = soup.find('a', {'title':'Website'}).findNext('a').get('href')
18 return info_data
19
AttributeError: 'NoneType' object has no attribute 'findNext'
Каждый город в теге dd, поэтому вы можете просто использовать функцию find_all(), чтобы получить имя и URL. Затем пройдите по каждому URL-адресу и получите таблицу. В примере всего 5 повторений, удаляем [:5] в цикле на полную
import requests
from bs4 import BeautifulSoup
import pandas as pd
def get_info(city_url: str) -> dict:
info_data = {}
response = requests.get(city_url)
soup = BeautifulSoup(response.text, 'lxml')
for x in soup.find('tbody').find_all(
lambda tag: tag.name == 'tr' and tag.get('class') == ['hintergrundfarbe-basis']):
if not x.get('style'):
if 'Koordinaten' in x.get_text():
info_data['Koordinaten'] = x.findNext('span', class_='coordinates').get_text()
else:
info_data[x.get_text(strip=True).split(':')[0]] = x.get_text(strip=True).split(':')[-1]
if soup.find('a', {'title': 'Website'}):
info_data['Web site'] = soup.find('a', {'title': 'Website'}).findNext('a').get('href')
return info_data
cities = []
response = requests.get('https://de.wikipedia.org/wiki/Liste_der_St%C3%A4dte_in_Deutschland#Liste_der_St%C3%A4dte_in_Deutschland')
soup = BeautifulSoup(response.text, 'lxml')
for city in soup.find_all('dd'):
city_url = 'https://de.wikipedia.org' + city.findNext('a').get('href')
result = {'City': city.get_text(), 'URL': 'https://de.wikipedia.org' + city.findNext('a').get('href')}
result |= get_info(city_url)
cities.append(result)
df = pd.DataFrame(cities)
print(df.to_string())
ВЫХОД:
City URL Koordinaten Bundesland Regierungsbezirk Landkreis Höhe Fläche Einwohner Bevölkerungsdichte Postleitzahl Vorwahl Kfz-Kennzeichen Gemeindeschlüssel Adresse derStadtverwaltung Bürgermeister Postleitzahlen Vorwahlen Stadtgliederung Oberbürgermeisterin Oberbürgermeister Erste Bürgermeisterin Erster Bürgermeister
0 Aach (BW) https://de.wikipedia.org/wiki/Aach_(Hegau) 47° 51′ N, 8° 51′ O Baden-Württemberg Freiburg Konstanz 545 m ü.NHN 10,68 km2 2384(31. Dez. 2022)[1] 223 Einwohner je km2 78267 07774 KN,STO 08 3 35 001 Hauptstraße 1678267 Aach Manfred Ossola NaN NaN NaN NaN NaN NaN NaN
1 Aachen (NW) https://de.wikipedia.org/wiki/Aachen 50° 47′ N, 6° 5′ O Nordrhein-Westfalen Köln Städteregion Aachen 175 m ü.NHN 160,85 km2 252.769(31. Dez. 2023)[1] 1571 Einwohner je km2 NaN NaN AC, MON 05 3 34 002 Markt52062 Aachen NaN 52062–52080 0241, 02405, 02407, 02408 7Stadtbezirke Sibylle Keupen(parteilos) NaN NaN NaN
2 Aalen (BW) https://de.wikipedia.org/wiki/Aalen 48° 50′ N, 10° 6′ O Baden-Württemberg Stuttgart Ostalbkreis 430 m ü.NHN 146,58 km2 68.816(31. Dez. 2022)[1] 469 Einwohner je km2 NaN NaN AA, GD 08 1 36 088 NaN NaN 73430–73434, 73453 07361, 07366, 07367 Kernstadtund 8Stadtbezirke NaN Frederick Brütting(SPD) NaN NaN
3 Abenberg (BY) https://de.wikipedia.org/wiki/Abenberg 49° 15′ N, 10° 58′ O Bayern Mittelfranken Roth 414 m ü.NHN 48,41 km2 5614(31. Dez. 2023)[1] 116 Einwohner je km2 91183 09178 RH, HIP 09 5 76 111 Stillaplatz 191183 Abenberg NaN NaN NaN 14Gemeindeteile NaN NaN Susanne König (parteilos) NaN
4 Abensberg (BY) https://de.wikipedia.org/wiki/Abensberg 48° 49′ N, 11° 51′ O Bayern Niederbayern Kelheim 370 m ü.NHN 60,26 km2 14.685(31. Dez. 2023)[1] 244 Einwohner je km2 93326 09443 KEH,MAI,PAR, RID,ROL 09 2 73 111 Stadtplatz 193326 Abensberg NaN NaN NaN 22Gemeindeteile NaN NaN NaN Bernhard Resch[2]
@zero, ты имеешь в виду веб-сайт?
@zero Таблица содержит ненужные метаданные и карты, которые нет смысла добавлять в выходную таблицу. Если вы хотите добавить веб-сайт, прежде чем возвращать переменную info_data, напишите - info_data['Web site'] = soup.find('a', {'title': 'Website'}).findNext('a').get('href')
на том же уровне пространства, что и return
или просто удали if not x.get('style'):
и всё получишь
привет дорогой Сергей! Я добавил дополнительную информацию в стартовый пост. кстати, спасибо за дополнительную информацию--
Конечно, карта нам не нужна. Контактные данные - это самое интересное здесь.
большое спасибо... кстати: update3: если я запущу этот код, чтобы получить 300 записей. это работает хорошо - если я запущу это, чтобы получить 2400, это не удастся.. - почему это так !?
@zero, наверное, у тебя ошибка 429 http? просто добавьте time.sleep(5) в цикл find_all, или вы получите еще одну ошибку?
Дорогой Сергей! Большое спасибо за ответ. Я запускаю это в google-colab - и с небольшим количеством результатов (всего 300 записей) все идет хорошо - но если я установлю * Soup.find_all('dd')#[:2500]:`это большое значение - тогда Я столкнулся с ошибками, описанными в последнем обновлении, которое я добавил в исходный пост — см. выше.
см. выше — результат, который я получаю… он содержит следующее утверждение: «AttributeError: Объект «NoneType» не имеет атрибута «findNext» и да — я запускаю его в Google Colab… хотелось бы услышать ваше мнение. ...
@zero у некоторых ссылок нет веб-сайта, я обновляю ответ и получаю полный результат
потрясающе - это намного больше, чем ожидалось - большой привет вам!! вы мне очень помогли!!
большое спасибо дорогой Сергей - это больше, чем ожидалось. Потрясающе. - Огромное спасибо! Кстати, как получить полные результаты, которые хранятся в файле df. - и содержащий все данные - в поле info.. (см. изображение выше) - с контактной информацией и т. д.