Разбор изменяющегося текста в HTML-теге Beautifulsoup Python

#python #beautifulsoup #html-parsing

#python #beautifulsoup #html-синтаксический анализ

Вопрос:

Я пытаюсь удалить числа и даты из диаграммы на Zillow. URL-адрес: https://www.zillow.com/austin-tx/home-values /

Область в html, с которой я работаю, это:

 <ul class="legend-entries" id="yui_3_18_1_1_1607476788112_1009">
            <li class="legend-value">Oct 2021</li>
            <li class="legend-entry legend-entry-0" id="yui_3_18_1_1_1607476788112_1330">Austin $464K</li>
<li class="hide legend-entry legend-entry-1"></li>
<li class="hide legend-entry legend-entry-2"></li>
<li class="hide legend-entry legend-entry-3"></li>
<li class="hide legend-entry legend-entry-4"></li>
<li class="hide legend-entry legend-entry-5"></li>
<li class="hide legend-entry legend-entry-6"></li>
</ul>
 

Я пытаюсь разобрать текст legend-value (октябрь 2021 года) и legend-entry (464 тыс. долларов США). Однако, когда вы наводите курсор мыши на точки на диаграмме (где эти данные существуют на странице), значения в html изменяются при каждом перемещении мыши.

Вот мой код до сих пор:

 from bs4 import BeautifulSoup

req_headers = {
    'accept': 'text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'en-US,en;q=0.8',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
}

all_data = []

url = 'https://www.zillow.com/austin-tx/home-values/'
r = s.get(url, headers=req_headers)
soup = BeautifulSoup(r.content, 'html.parser')
#soup.find (class_= 'legend-entries')

for ul in soup.find_all('ul'):
    lis=ul.find_all('li')
    for elem in lis:
        all_data.append(elem.text.strip())
 

Я чувствую, что это должно сработать, но оно ничего не возвращает. Хэшированная строка в моем коде вернет legend-entries , по крайней мере, тег. Я не уверен, как этого добиться.

Комментарии:

1. Это было сгенерировано javascript. Каков ваш ожидаемый результат?

Ответ №1:

Этот график возникает из вызова API. Вы можете извлечь это и перестроить данные.

Вот как:

 from datetime import datetime
import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0",
    "X-Requested-With": "XMLHttpRequest",
}
api_url = "https://www.zillow.com/ajax/homevalues/data/timeseries.json?r=10221amp;m=zhvi_plus_forecastamp;dt=111"
graph = requests.get(api_url, headers=headers).json()
time_ = graph["10221;zhvi_plus_forecast;111"]["data"]
for moment in time_:
    date = datetime.fromtimestamp(moment["x"] // 1000).date()
    value = moment["y"]
    print(f"{date} - ${value}")
 

Вывод:

 2010-12-31 - $224771
2011-01-31 - $224297
2011-02-28 - $223623
2011-03-31 - $223053
2011-04-30 - $222571
2011-05-31 - $221931
2011-06-30 - $221322
2011-07-31 - $220837
2011-08-31 - $221413
2011-09-30 - $222088
2011-10-31 - $222520
2011-11-30 - $222665
2011-12-31 - $222788
2012-01-31 - $223433
2012-02-29 - $224288
2012-03-31 - $225461
and so on ...
 

Или вы можете построить это и иметь свой собственный график (кто сказал, что вы не можете, верно?).

 from datetime import datetime

import matplotlib.pyplot as plt
import pandas as pd
import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0",
    "X-Requested-With": "XMLHttpRequest",
}
api_url = "https://www.zillow.com/ajax/homevalues/data/timeseries.json?r=10221amp;m=zhvi_plus_forecastamp;dt=111"
graph = requests.get(api_url, headers=headers).json()

df = pd.DataFrame(graph["10221;zhvi_plus_forecast;111"]["data"])
plt.figure(1)
plt.plot(df['x'].apply(lambda x: datetime.fromtimestamp(x // 1000).date()), df['y'])
plt.show()

 

Вывод:

введите описание изображения здесь

Комментарии:

1. Это большое спасибо! Единственное, что мне интересно, это откуда вы знаете, какой тег api находится в этом html?

2. Я даже не смотрел на HTML. Я нашел конечную точку API в инструменте разработчика -> Сеть -> XHR.

3. не могли бы вы помочь мне немного подробнее — что я ищу на этой вкладке XHR? Пытаюсь провести некоторое исследование по этому вопросу прямо сейчас, но, похоже, это слишком сложно.

4. По сути, вы просматриваете трафик своего браузера, и то, что вы хотите найти, — это запрос, который содержит данные для этого графика, потому что, если вы отключите JavaScript, этого графика там не будет. Поэтому он должен быть «отображен» динамически из какой-либо другой структуры. Эта структура представляет собой объект JSON, который возвращается вместе с этим запросом — imgur.com/a/jfi9Zkh

5. Поскольку API понимает их, amp; но 10221;zhvi_plus_forecast;111 является ключом в этом объекте JSON, который вы получаете обратно в качестве ответа. Затем я могу получить доступ к data списку и построить график. Волшебство! : D