【问题标题】:Webscraping Javascript enabled website using Selenium in C#使用 C# 中的 Selenium 抓取启用 Javascript 的网站
【发布时间】:2018-09-14 01:41:52
【问题描述】:

我正在尝试刮字典,字典网站页面是这样的:

  • 有一个用于输入单词的搜索框

  • 有一个按钮,输入单词后必须点击它才能看到结果

  • 问题是网站是用JavaScript设计的,这意味着当我点击Go按钮时,网页URL没有改变,只是div里面的内容改变了,<div id="dict_entry">content of the entry for the given word goes here</div>

  • 请注意,当点击 go 按钮时,搜索框内容会通过 JavaScript 使用 post 方法发布到服务器。

这是我当前的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System.IO;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var driver = new ChromeDriver())
            {

                driver.Navigate().GoToUrl("http://www.mydictionary.com/dictionary");
                var searchField = driver.FindElementById("search");
                var searchButton = driver.FindElementByXPath("//*[@id=\"search_submit\"]");
                searchField.SendKeys("writer");
                searchButton.Click();
                var result = driver.FindElementByXPath("//*[@id=\"dict_entry\"]").Text;
                File.WriteAllText("result.txt", result);



            }
        }
    }
}

上述代码的问题在于,当我导航到http://mydictionary.com/dictionary 时,字典会加载默认的第一个条目,即单词的条目:a,而我正在尝试获取单词的条目:writer但是我的代码获取了单词a 的内容,因为它不会等待表单提交到服务器并在抓取网页之前获得其响应。由于网页是 JavaScript 驱动的,我如何确保我的 JavaScript 表单帖子的响应已经返回,以便在获取新的 JavaScript 操作的 DOM 后将其抓取?

换句话说:如何在网页抓取之前等待 JavaScript 新创建的 DOM?

【问题讨论】:

  • 为什么不直接重现当您在浏览器中单击“开始”按钮并提交网络表单时产生的相同 XHR?
  • 请给我一个例子
  • @acman123 当您单击“控制台”和“网络”选项卡中的“搜索”按钮时,您可以使用浏览器检查网站的活动。那么你可以更好地进行报废。
  • @acman123 看看XHR examples。检查在 e 中提交表单时记录的 XHR。 G。 Chrome 开发者工具,网络选项卡,你可以找到应该发送的参数。请指定一些示例 URL 以进一步了解。
  • 该网站使用身份验证,因此我需要适当的 cookie,并且只有通过使用网络浏览器才能获得这些 cookie

标签: javascript c# selenium selenium-webdriver web-scraping


【解决方案1】:

我找到了这个等待 jquery 完成的解决方案,它似乎正在工作:

while (true) // Handle timeout somewhere
    {
        var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
        if (ajaxIsComplete)
            break;
        Thread.Sleep(100);
    }

https://sqa.stackexchange.com/a/2733

【讨论】:

    【解决方案2】:

    使用下面的代码显式等待 Web 元素

    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    wait.Until(ExpectedConditions.ElementIsVisible(By.Id("id")));
    

    然后得到结果。

    【讨论】:

    • 您的代码的问题是该项目已经可见,因为字典中的所有条目共享相同的 css 类和 id 名称。在字典中搜索单词时,只有这些 div 的内容不会改变 id 名称或类名。
    【解决方案3】:

    你能不能在SendKeys()之前先尝试使用Clear()方法

    searchField.Clear();
    searchField.SendKeys("writer");
    

    【讨论】:

    • 你的回答完全无关
    猜你喜欢
    • 2011-03-22
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    相关资源
    最近更新 更多