如何用C#和HTML-Agility-Pack获取Steam市场动态加载的价格信息?
解决Steam市场动态数据提取问题
你遇到的核心问题是:Steam市场的在售/求购数量、价格这类数据并非嵌入在初始HTML中,页面加载完成后是通过JavaScript异步调用Steam内部API获取并渲染的。HTML Agility Pack只能解析服务器返回的静态HTML,自然拿不到这些动态生成的内容。
下面提供两种可行的解决方案:
方案1:使用浏览器自动化工具(以Playwright为例)
通过模拟真实浏览器的行为,等待页面完全渲染后再提取数据,适合不想研究API的场景:
- 先安装Playwright的NuGet包:
Microsoft.Playwright - 执行以下代码:
using Microsoft.Playwright; class Program { static async Task Main(string[] args) { using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true }); var page = await browser.NewPageAsync(); // 加载目标页面 await page.GotoAsync("https://steamcommunity.com/market/listings/753/433340-Pink%20Slime"); // 等待价格区域加载完成(选择器可根据页面实际调整) await page.WaitForSelectorAsync(".market_commodity_orders_header_promote"); // 提取在售价格与数量 var sellPrice = await page.InnerTextAsync(".market_commodity_orders_table .market_commodity_order_price:first-of-type"); var sellCount = await page.InnerTextAsync(".market_commodity_orders_table .market_commodity_order_amount:first-of-type"); // 提取求购价格与数量 var buyPrice = await page.InnerTextAsync(".market_commodity_orders_table .market_commodity_order_price:nth-of-type(2)"); var buyCount = await page.InnerTextAsync(".market_commodity_orders_table .market_commodity_order_amount:nth-of-type(2)"); Console.WriteLine($"在售价格: {sellPrice}, 在售数量: {sellCount}"); Console.WriteLine($"求购价格: {buyPrice}, 求购数量: {buyCount}"); } }
方案2:直接调用Steam市场API(更高效)
Steam市场的数据来自专门的API接口,直接请求接口获取JSON数据,速度更快、资源占用更低:
- 从初始HTML中提取商品的唯一标识
item_nameid - 构造API请求URL,获取并解析JSON数据
using System.Net.Http; using System.Text.Json; class Program { static async Task Main(string[] args) { var targetUrl = "https://steamcommunity.com/market/listings/753/433340-Pink%20Slime"; using var httpClient = new HttpClient(); // 第一步:提取item_nameid var htmlContent = await httpClient.GetStringAsync(targetUrl); var nameIdStart = htmlContent.IndexOf("item_nameid") + 13; var nameIdEnd = htmlContent.IndexOf("\"", nameIdStart); var itemNameId = htmlContent.Substring(nameIdStart, nameIdEnd - nameIdStart); // 第二步:请求API接口(参数可根据地区调整,currency=2对应人民币) var apiUrl = $"https://steamcommunity.com/market/itemordershistogram?country=CN&language=schinese¤cy=2&item_nameid={itemNameId}"; var apiJson = await httpClient.GetStringAsync(apiUrl); // 解析JSON数据 var jsonDoc = JsonDocument.Parse(apiJson); var sellSummary = jsonDoc.RootElement.GetProperty("sell_order_summary").GetString(); var buySummary = jsonDoc.RootElement.GetProperty("buy_order_summary").GetString(); Console.WriteLine($"在售汇总: {sellSummary}"); Console.WriteLine($"求购汇总: {buySummary}"); // 如需详细的价格档位数据,解析sell_order_table数组 foreach (var order in jsonDoc.RootElement.GetProperty("sell_order_table").EnumerateArray()) { var price = order[0].GetString(); var count = order[1].GetString(); Console.WriteLine($"售价: {price}, 对应数量: {count}"); } } }
方案对比
- 浏览器自动化:无需研究API结构,兼容性强,但运行速度慢、资源消耗大,适合小批量抓取。
- API调用:速度快、资源占用低,但需要处理API参数,Steam的接口可能会有小范围调整,需注意维护。
内容的提问来源于stack exchange,提问作者ElyesBRD
相关产品推荐
相关产品推荐

