BeautifulSoup:抓取蒸汽愿望清单游戏 - .findAll 不返回在检查器中可见的嵌套 div
Posted
技术标签:
【中文标题】BeautifulSoup:抓取蒸汽愿望清单游戏 - .findAll 不返回在检查器中可见的嵌套 div【英文标题】:BeautifulSoup: Scraping steam wishlist games - .findAll not returning nested divs visible in inspector 【发布时间】:2020-04-13 19:37:49 【问题描述】:所以我正在尝试使用 beautifulsoup 从我的 Steam 愿望清单中删除游戏。理想情况下,我想要游戏名称、游戏 Steam 商店页面的链接以及当前列出的价格。问题是,当我调用soup.find_all("div", "class": "wishlist_row")
时,它返回一个空列表,尽管我能够看到检查器中我的愿望列表中的每个游戏都应该有几个这样的 div。这是我当前代码的精简版:
from bs4 import BeautifulSoup
import requests
profile_id = "id/Zorro4"
url_base = "https://store.steampowered.com/wishlist/"
r = requests.get(url_base + profile_id + "#sort=order", headers=header)
data = r.text
soup = BeautifulSoup(data, features="lxml")
# find divs containing information about game and steam price
divs = soup.findAll("div", "class": "wishlist_row")
print(divs)
>>> []
如果我转到https://store.steampowered.com/wishlist/id/zorro4/#sort=order,我可以在检查器中清楚地看到这些 div 我试过了
使用 html.parser 代替 lxml 欺骗用户代理/标头 尝试改用.find("div", "class": "wishlist_row")
通过这些线程查看,等等
Parsing nested divs with BeautifulSoup
Beautiful Soup and extracting a div and its contents by ID
BeautifulSoup can't find required div
我注意到一些奇怪的东西可能有助于解决问题,但我不知道该怎么做。
soup.find(id="wishlist_ctn") # The div which should contain all the wishlist_row divs
>>> <div id="wishlist_ctn">\n</div>
据我所知,这应该返回<div id="wishlist_ctn">...</div>
,因为 div 包含更多嵌套的 div(我正在寻找的那些)。我不确定为什么它只返回一个换行符。就好像在抓取 wishlist_ctn div 的内容时丢失了一样。任何帮助将不胜感激,过去几天我一直在尝试解决这个问题,但没有成功。
【问题讨论】:
【参考方案1】:您在网页上看到的数据是通过 javascript/JSON 动态加载的。
加载数据的 URL 位于 HTML 页面内 - 我们可以使用 re
模块来提取它。
此示例打印愿望清单的 JSON 数据:
import re
import json
import requests
url = 'https://store.steampowered.com/wishlist/id/zorro4/#sort=order'
wishlist_url = json.loads( re.findall(r'g_strWishlistBaseURL = (".*?");', requests.get(url).text)[0] )
data = requests.get(wishlist_url + 'wishlistdata/?p=0').json()
print(json.dumps(data, indent=4))
打印:
"50":
"name": "Half-Life: Opposing Force",
"capsule": "https://steamcdn-a.akamaihd.net/steam/apps/50/header_292x136.jpg?t=1571756577",
"review_score": 8,
"review_desc": "Very Positive",
"reviews_total": "5,383",
"reviews_percent": 95,
"release_date": "941443200",
"release_string": "1 Nov, 1999",
"platform_icons": "<span class=\"platform_img win\"></span><span class=\"platform_img mac\"></span><span class=\"platform_img linux\"></span>",
"subs": [
"id": 32,
...and so on.
【讨论】:
您应该增加p
并在收到游戏时循环播放。虽然您的代码可能适用于这个特定的 steamid,但它不适用于其他人,因为第 0 页的响应将只包含前 100 个游戏。
谢谢!无论如何要使用 json 库导航输出,还是我必须使用 .split() 并手动解析它?
@Jurij 不,data
变量的类型为 dict
,因此您可以像使用普通 python 字典一样使用它。【参考方案2】:
问题在于愿望清单实际上是由 AJAX 请求填充的。 Beautiful Soup 不处理该功能。你需要一个网络驱动程序。幸运的是,这里的捷径是只使用为愿望清单进行的 API 调用并解析 JSON 响应。在这种情况下,请求是:
https://store.steampowered.com/wishlist/profiles/76561198068616380/wishlistdata/?p=0
【讨论】:
非常感谢!您能否详细说明您是如何获得该链接的/对于这些通过 JSON 动态加载数据的情况,获得此类链接的一般流程是什么? 浏览器上的开发者工具将显示来自加载页面的所有请求。然后你可以按类型过滤掉:图片、css、js等。我在这里假设但数字字符串可能是用户ID或类似的东西;你会为每个用户改变它。以上是关于BeautifulSoup:抓取蒸汽愿望清单游戏 - .findAll 不返回在检查器中可见的嵌套 div的主要内容,如果未能解决你的问题,请参考以下文章