【问题标题】:Html Agility Pack how to get dynamically generated content after page loadsHtml Agility Pack 如何在页面加载后获取动态生成的内容
【发布时间】:2020-07-01 06:59:57
【问题描述】:

我正在尝试从“https://www.sideshow.com/collectibles?manufacturer=Hot+Toys”获取信息 特别是 Div c-ProductList 行 ss-targeted 但似乎没有检索到任何信息,任何线索

var test = page.DocumentNode.SelectNodes("//div[@class='c-ProductList row ss-targeted']");

【问题讨论】:

    标签: c# web-scraping html-agility-pack


    【解决方案1】:

    您想要获取的内容是在页面加载后使用 Javascript 和 Ajax 生成的。 HAP 无法获取它,除非它在后台运行浏览器并执行页面上的脚本。

    .Net Core 2.0

    先决条件:您需要在 PC 上安装 Chrome 网络浏览器。

    1. 创建控制台应用程序

    2. 安装 Nuget 包 Install-Package HtmlAgilityPack Install-Package Selenium.WebDriver Install-Package Selenium.Chrome.WebDriver

    3. Main方法替换为以下

    代码:

        static void Main(string[] args)
        {
            string url = "https://www.sideshow.com/collectibles?manufacturer=Hot+Toys";
            var browser = new ChromeDriver(Environment.CurrentDirectory);
            browser.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
            browser.Navigate().GoToUrl(url);
    
            var results = browser.FindElementByClassName("ss-results");
            var doc = new HtmlDocument();
            doc.LoadHtml(results.GetAttribute("innerHTML"));
    
            // Show results
            var list = doc.DocumentNode.SelectSingleNode("//div[@class='c-ProductList row ss-targeted']");
            foreach (var title in list.SelectNodes(".//h2[@class='c-ProductListItem__title ng-binding']"))
            {
                Console.WriteLine(title.InnerText);
            }
            Console.ReadLine();
        }
    

    .Net 4.6

    1. 创建控制台应用程序

    2. 安装 Nuget 包Install-Package HtmlAgilityPack

    3. Solution Explorer中添加对System.Windows.Form的引用

    4. 根据需要添加using语句

    5. Main 方法替换为以下内容

    代码:

    [STAThread]
    static void Main(string[] args)
    {
        string url = "https://www.sideshow.com/collectibles?manufacturer=Hot+Toys";
    
        var web = new HtmlWeb();
        web.BrowserTimeout = TimeSpan.FromSeconds(30);
    
        var doc = web.LoadFromBrowser(url, o =>
        {
            var webBrowser = (WebBrowser)o;
    
            // Wait until the list shows up
            return webBrowser.Document.Body.InnerHtml.Contains("c-ProductList");
        });
    
        // Show results
        var list = doc.DocumentNode.SelectSingleNode("//div[@class='c-ProductList row ss-targeted']");
        foreach (var title in list.SelectNodes(".//h2[@class='c-ProductListItem__title ng-binding']"))
        {
            Console.WriteLine(title.InnerText);
        }
        Console.ReadLine();
    }
    

    显示以:

    开头的列表

    钢铁侠马克L

    约翰威克

    惩罚者战争机器装甲

    神奇女侠豪华版

    【讨论】:

    • 我正在使用 .Net Core 2.0 :(
    • @DeanBeckerton 根据documentation,Core 中没有WebBrowser 类。该问题未标记为核心,但我已按照 HAP 网站中的建议更新了我的答案以支持它。
    • @derloopkat 该解决方案看起来很有希望,我想在使用 .net 4.6、ASP.net 编写的网站中使用它。您能否更新此环境的答案。我尝试在此处实施解决方案,但出现错误,例如“HtmlWeb 不包含“LoadFromWeb”的定义。
    • @giparekh,方法名是LoadFromBrowser()。我已经在 4.6 中进行了测试,并且可以正常工作。包版本是<package id="HtmlAgilityPack" version="1.11.18" targetFramework="net46" />。可能是您的版本较旧或方法名称拼写错误。
    • 完美。我使用的是旧版本。较新的版本已解决该问题。但现在开始出现新异常,因为“ThreadStateException:ActiveX 控件 '8856f961-340a-11d0-a96b-00c04fd705a2' 无法实例化,因为当前线程不在单线程单元中。”在 LoadFromBrowser()。实际上,我要从网站cmegroup.com/trading/interest-rates/us-treasury/… 中删除数据,这里的元素是“td”,id 为 A“quotesFuturesProductTable1_ZNU0_last”,但 doc.DocumentNode.SelectSingleNode 返回 null。
    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 2014-02-08
    • 2011-11-19
    相关资源
    最近更新 更多