【问题标题】:Parse Changing Text in HTML tag Beautifulsoup Python解析 HTML 标签 Beautifulsoup Python 中的更改文本
【发布时间】:2021-03-20 10:44:36
【问题描述】:

我正在尝试从 Zillow 的图表中删除数字和日期。 网址为: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 年 10 月)和 legend-entry($464K)文本。但是,当您将鼠标悬停在图表上的点上(页面上存在此数据的位置)时,每当您移动鼠标时,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 标记。我不确定如何实现这一点。

【问题讨论】:

  • 这是由 javascript 生成的。您的预期输出是什么?

标签: python beautifulsoup html-parsing


【解决方案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=10221&m=zhvi_plus_forecast&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=10221&m=zhvi_plus_forecast&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()

输出:

【讨论】:

  • 这太好了,谢谢!我唯一想知道的是你怎么知道那个html中的api标签是什么?
  • 我什至没有看 HTML。我在 Developer Tool -> Network -> XHR 中找到了 API 端点。
  • 你能帮我进一步吗 - 我在 XHR 选项卡中寻找什么?目前正在尝试对此进行一些研究,但似乎需要吸收很多内容。
  • 您基本上是在查看浏览器的流量,而您要查找的是携带该图数据的请求,因为如果您关闭 JavaScript,则该图不存在。所以它必须从其他结构中动态地“渲染”。该结构是一个 JSON 对象,它与此请求一起返回 - imgur.com/a/jfi9Zkh
  • 因为 API 理解那些 &amp;10221;zhvi_plus_forecast;111 是您作为响应返回的 JSON 对象中的一个键。然后,我可以访问data 列表并绘制图表。魔法! :D
猜你喜欢
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 2017-10-30
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多