Почему не содержит текст в BeautifulSoup, несмотря на то, что точно такой же с сайта содержит его?

#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)