#python #html #web-scraping #beautifulsoup
Вопрос:
Я должен удалить 3 элемента с этого сайта:
http://www.altitude-maps.com/city/170_562,Poznan,Wielkopolskie,Poland
Мне нужны широта, долгота и высота, поэтому мой код:
import requests
from bs4 import BeautifulSoup as bs
url = 'http://www.altitude-maps.com/city/170_562,Poznan,Wielkopolskie,Poland'
r = requests.get(url)
soup = bs(r.content, features="html.parser")
latitude = soup.find('span', attrs={'id': 'curLat'}).get_text()
longitude = soup.find('span', attrs={'id': 'curLng'}).get_text()
elevation1 = soup.find('span', attrs={'id': 'altitude'}).get_text() # from the text in the center
elevation2 = soup.find('span', attrs={'id': 'curElevation'}).get_text() # from the box in the left
Он находит значения для широты и долготы, но не для высоты (в обоих случаях). Вместо того, чтобы получить «80,33 м» и » 80,33 м (263,55 фута)», я получаю пустое пространство и пустую улицу.
Сравнение HTML из BS и с веб-сайта:
BS_elevation1 = soup.find('span', attrs={'id': 'altitude'})
# BS_elevation1: <span id="altitude" style="font-size: 1.5em;"> </span>
# This part on the website: <span id="altitude" style="font-size: 1.5em;">80.33 m (263.55 ft)</span>
BS_elevation2 = soup.find('span', attrs={'id': 'curElevation'})
# BS_elevation2: <span id="curElevation" style=""></span>
# This part on the website: <span id="curElevation" style>80.33 m</span>
Похоже, что текст доступен на веб-сайте, но он недоступен в BeautifulSoup. Я не могу понять, почему это происходит. Как с этим справиться?
Ответ №1:
import httpx
import trio
import re
async def main():
async with httpx.AsyncClient(timeout=None) as client:
r = await client.get('http://www.altitude-maps.com/city/170_562,Poznan,Wielkopolskie,Poland')
goal = re.findall(r"(lati|long|elev).*?'(. )'", r.text)
print(goal)
if __name__ == "__main__":
trio.run(main)
Выход:
[('lati', '52.4063740'), ('long', '16.9251681'), ('elev', '80.329216003418')]
Комментарии:
1. @QHarr, какую версию Python/Trio вы используете ?
2. @QHarr Звучит странно. как называется сам сценарий ? также, что происходит, когда вы запускаете свой скрипт через
python script.py
? убедитесьtrio
, что в той же папке каталога нет файла с таким именем !3. @QHarr 🙂 это случается несколько раз
4. @QHarr :На самом деле я один из его авторов, обязательно дайте мне знать, если у вас возникнут какие-либо вопросы по этому поводу или какие-либо. я любитель асинхронности 🙂
5. @QHarr извините, только что получил уведомление. должен ли я применить пример на реальном веб-сайте, который у вас есть ?
Ответ №2:
Информация, которую вы ищете, встроена в <script>
тег страницы внутри, поэтому BeautifulSoup ее не видит. Однако вы можете использовать re
модуль для анализа страницы.
Чтобы получить широту, долготу и высоту, вы можете использовать этот пример:
import re
import requests
url = "http://www.altitude-maps.com/city/170_562,Poznan,Wielkopolskie,Poland"
text = requests.get(url).text
lat = re.search(r"geoplugin_latitude.*?([d.-] )", text).group(1)
lon = re.search(r"geoplugin_longitude.*?([d.-] )", text).group(1)
elv = re.search(r"geoip_elevation.*?([d.-] )", text).group(1)
print("Latitude:", lat)
print("Longitude:", lon)
print("Elevation:", elv)
С принтами:
Latitude: 52.4063740
Longitude: 16.9251681
Elevation: 80.329216003418
Ответ №3:
Потому что высота не заполняется при представлении страницы. Сделайте «просмотр исходного кода» в своем браузере, и вы увидите, что он заполнен Javascript.
Однако обратите внимание, что все нужные вам данные присутствуют в коде Javascript во втором блоке Javascript. Это должно быть довольно легко разобрать.
Комментарии:
1. Спасибо, теперь я понимаю, что там произошло. Я понимаю, почему мне удалось соскрести широту и долготу, но мой вопрос таков: почему широта и долгота указаны в источнике веб-сайта, а высота-нет? Я предполагаю, что каждый элемент зависит от кода Javascript во втором блоке Javascript, так в чем же разница между широтой/долготой и высотой? Поправьте меня, если мое предположение неверно.
Ответ №4:
Аналогичная идея регулярного выражения, но с использованием понимания словаря
import re, requests
items = ['latitude', 'longitude', 'elevation']
r = requests.get('http://www.altitude-maps.com/city/170_562,Poznan,Wielkopolskie,Poland').text
data = {item: re.search(r"(?<={}).*'(.*?)'".format(item), r).group(1) for item in items}
print(data)