c# - 使用异步 linq 过滤 Puppeter Sharp 的 ElementHandle[]

标签 c# linq selenium-webdriver puppeteer puppeteer-sharp

我一直在 Puppeter Sharp 中重写我的 Selenium 应用程序,以了解有关该框架的更多信息。我的应用程序运行在一个我无法访问并修改其源代码的网站上,我只是收集了一些信息。

基于此,我使用 Selenium 编写了一个函数,可以过滤 IEnumerable<IWebElement> 中所需的元素。 ,这样:

var element = Driver.FindElements(By.Id("User"))
    .First(x => 
           x.Text.ToLower().Trim() == "AAA" &&
           x.FindElement(By.Id("contact")).Text.ToLower().Trim() == "BBB")
    .FindElement(By.XPath("../input"));

但是我无法使用 Puppeteer Sharp 编写执行相同操作的代码。我写的最准确的方法是:

var users = await Page.QuerySelectorAllAsync("#User");
var baseElement = users.First(async x =>
    (await x.JsonValueAsync<string>()).ToLower().Trim() == "AAA" &&
    (await (await x.QuerySelectorAsync("#contact")).JsonValueAsync<string>()).ToLower().Trim() == "BBB");
var element = await baseElement.XPathAsync("../input");

上面的代码仍然返回一个错误:

Cannot convert async lambda expression to delegate type 'Func'.

是的,这是有道理的,但我无法找到另一种使用 linq 的方法,以使其至少清晰且小。

编辑:

Html 示例如下:我需要根据攻击名称和类型返回 radio 输入。我知道我可以编写一个很棒、丑陋且难以辨认的 xpath 来为我查询它,但我尝试采用一种更具可读性和流畅性的方法来更容易维护。

<div id="player">
    <div class="attklist">
        <h2>Choose an Attack</h2>
        <ul>
            <li class="batsel" style="cursor: pointer;">
                <input type="radio" value="1" name="selected" checked="checked" id="atkopt1">
                <label for="atkopt1">Strength
                    <br><span class="tbtn tbtn-normal">normal</span>
                </label>
            </li>
            <li style="cursor: pointer;">
                <input type="radio" value="2" name="selected" id="atkopt2">
                <label for="atkopt2">Strength
                    <br><span class="tbtn tbtn-fighting">fighting</span>
                </label>
            </li>
            <li style="cursor: pointer;">
                <input type="radio" value="3" name="selected" id="atkopt3">
                <label for="atkopt3">Spectre Slash
                    <br><span class="tbtn tbtn-ghost">ghost</span>
                </label>
            </li>
            <li style="cursor: pointer;">
                <input type="radio" value="4" name="selected" id="atkopt4">
                <label for="atkopt4">Fire Puch
                    <br><span class="tbtn tbtn-fire">fire</span>
                </label>
            </li>
        </ul>
    </div>
</div>

最佳答案

从技术上讲,这是 Linq 方法中缺少的功能。编写 Async Linq 函数并不是那么简单。

另一方面,我发现直接用 JavaScript 实现要简单得多。为什么?因为您可以在浏览器中测试脚本,然后将其移至 C# 代码。

例如,此方法将查找所有 li 元素,找到带有文本 fire 的 span 的 li,然后单击输入.

await page.EvaluateFunctionAsync(@"() => {
     Array.from(document.querySelectorAll('li'))
         .find(l => l.querySelector('span').innerText === 'fire').querySelector('INPUT').click();
}");

关于c# - 使用异步 linq 过滤 Puppeter Sharp 的 ElementHandle[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53141815/

相关文章:

c# - IdentityServer4 ValidIssuers

c# - 通过两个属性比较两个对象

c# - Entity Framework FirstOrDefault 用构造函数值覆盖?

.net - linq 表达式的构造方式是否存在性能差异?

java - 与 Selenium 和 JXL 比较值

c# - LINQ 联盟与 SQL 联盟

c# - 使用@init 语句导入语法时出现问题

c# - 有没有办法获取 LINQ 查询创建的 SQL?

java - Selenium 悬停代码适用于 Chrome 而不是 Edge

java - Selenium 页面对象模式定位器参数