RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 606754
Accepted
iluxa1810
iluxa1810
Asked:2020-12-23 01:00:16 +0000 UTC2020-12-23 01:00:16 +0000 UTC 2020-12-23 01:00:16 +0000 UTC

我如何通过控制台应用程序与站点交互?

  • 772

假设有一个站点,上面有一些字段。

您需要向该字段发送一些值,单击按钮,然后获得一个新页面,您可以在其中转到第一个链接。

我需要为这些参考 WebBrowser 类吗?

如果可能,请给出一个示例(例如,您可以使用目标站点 google,但不使用其 API。)

c#
  • 7 7 个回答
  • 10 Views

7 个回答

  • Voted
  1. Vadim Ovchinnikov
    2020-12-30T06:24:16Z2020-12-30T06:24:16Z

    谷歌在控制台

    我将向您展示一个允许您直接在控制台中使用 google 的程序示例(提取google.com上的第一个标题搜索链接):

    前期工作

    使用 CefSharp,一个基于 Chromium 的包装库。this answer 对此进行了非常详细的描述。只需通过 Nuget 包安装。

    Install-Package CefSharp.OffScreen -Version 57.0.0
    

    通过从我的答案中复制这两个类 (CefSharpWrapper和ConvertHelper),您已经有了一个框架程序,您可以使用它直接从控制台应用程序执行任何 JavaScript。


    也设置x64或x86作为平台。该平台Any CPU 受支持,但需要额外的代码。

    其他属性和方法

    同样对于此任务,添加到CefSharpWrapper属性Address:

    public string Address => _browser.Address;
    

    和方法WaitTillAddressChanges:

    public void WaitTillAddressChanges()
    {
        // wait till address changes
        AutoResetEvent waitHandle = new AutoResetEvent(false);
    
        EventHandler<AddressChangedEventArgs> onAddressChanged = null;
    
        onAddressChanged = (sender, e) =>
        {
            _browser.AddressChanged -= onAddressChanged;
    
            waitHandle.Set();
        };
    
        _browser.AddressChanged += onAddressChanged;
    
        waitHandle.WaitOne();
    }
    

    程序本身的一个例子

    这是程序本身的示例(类Program,方法Main):

    public class Program
    {
        private static void Main()
        {
            MainAsync().Wait();
        }
    
        private static async Task MainAsync()
        {
            CefSharpWrapper wrapper = new CefSharpWrapper();
    
            wrapper.InitializeBrowser();
    
            Console.Write("Введите поисковой запрос: ");
    
            string searchText = Console.ReadLine();
    
            string[] urls = await wrapper.GetResultAfterPageLoad("https://google.com", async () =>
            {
                await wrapper.EvaluateJavascript(
    // заполняем тесковое поле
    $@"document.getElementById('lst-ib').value = '{searchText}';
    // выполняем submit поисковой формы
    document.getElementById('tsf').submit()");
    
                // Ждём когда перейдёт на результаты поиска
                wrapper.WaitTillAddressChanges();
    
                // Когда страница результатов поиска полностью подгрузится, излекаем результаты
                return await wrapper.GetResultAfterPageLoad(wrapper.Address, async () =>
                    await wrapper.EvaluateJavascript<string[]>(
                        // получаем результаты
                        "Array.prototype.map.call(document.querySelectorAll('h3.r > a'), (a) => a.href);"));
            });
    
            Console.WriteLine("Первые ссылки поиска:");
    
            foreach (string url in urls)
            {
                Console.WriteLine(url);
            }
    
            wrapper.ShutdownBrowser();
        }
    }
    

    计划成果

    例如,如果我输入“parse html C#”:

    计划成果


    阿贾克斯

    使用此库处理 AJAX也非常方便。

    • 21
  2. Best Answer
    iluxa1810
    2020-12-23T02:24:14Z2020-12-23T02:24:14Z

    我找到了一个有趣的库Selenium,通过驱动程序,您可以使用它与真实的浏览器进行交互。非常容易管理:

    using OpenQA.Selenium;
    using OpenQA.Selenium.Firefox;
    
    // Requires reference to WebDriver.Support.dll
    using OpenQA.Selenium.Support.UI;
    
    class GoogleSuggest
    {
        static void Main(string[] args)
        {
            // Create a new instance of the Firefox driver.
            // Note that it is wrapped in a using clause so that the browser is closed 
            // and the webdriver is disposed (even in the face of exceptions).
    
            // Also note that the remainder of the code relies on the interface, 
            // not the implementation.
    
            // Further note that other drivers (InternetExplorerDriver,
            // ChromeDriver, etc.) will require further configuration 
            // before this example will work. See the wiki pages for the
            // individual drivers at http://code.google.com/p/selenium/wiki
            // for further information.
            using (IWebDriver driver = new FirefoxDriver())
            {
                //Notice navigation is slightly different than the Java version
                //This is because 'get' is a keyword in C#
                driver.Navigate().GoToUrl("http://www.google.com/");
    
                // Find the text input element by its name
                IWebElement query = driver.FindElement(By.Name("q"));
    
                // Enter something to search for
                query.SendKeys("Cheese");
    
                // Now submit the form. WebDriver will find the form for us from the element
                query.Submit();
    
                // Google's search is rendered dynamically with JavaScript.
                // Wait for the page to load, timeout after 10 seconds
                var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
                wait.Until(d => d.Title.StartsWith("cheese", StringComparison.OrdinalIgnoreCase));
    
                // Should see: "Cheese - Google Search" (for an English locale)
                Console.WriteLine("Page title is: " + driver.Title);
            }
        }
    }
    

    但是,我仍然想知道如何使用标准的 .NET 工具来做到这一点。

    • 8
  3. Qutrix
    2020-12-28T00:00:20Z2020-12-28T00:00:20Z

    如果您只需要对站点的某些众所周知的部分进行编码,您可以简单地提取浏览器发送的必要请求(您可以在浏览器开发人员控制台中隔离它们,通常在网络选项卡上)并发送在程序中请求,例如通过HttpClient.

    如果最初你不知道请求本身(你需要在程序本身中动态接收它们),那么事件可以有 2 个选项:

    1. 如果该网站可以在不使用 ajax 的情况下工作 - 解析页面的标签<form>并从它开始。它有一个action包含路径的属性和一个指定编码格式的编码属性(如果没有,默认是“ application/x-www-form-urlencoded”,看起来,虽然通过开发者控制台查看肯定更好)。您收集所有这些,包括标签内的参数<form>,将其发送HttpClient并获得响应
    2. 如果该站点仅通过 ajax 工作,那已经很困难了,除了通过网络手动查看正在形成哪些请求并对它们进行硬编码之外,我看不到任何其他出路

    但在大多数情况下,通常使用自己的参数发送预先准备好的(隔离的)请求就足够了。

    您还可以绑定到HttpClient'yHttpClientHandler以存储 cookie 和其他好东西。

    例如,您需要在某个时间向墙上添加一个帖子——算法将如下所示:

    1. HttpClient附上HttpClientHandler'om创建
    2. 通过它向所需地址发送一个 POST 请求(您可以在源代码中的 VK 页面上看到它或通过开发人员控制台将其隔离),并将您的登录名和密码作为值。该请求将返回一个响应,但在这种情况下不需要,只需等待它到达HttpResponseMessage,以便我们收到 cookie
    3. 发送另一个 POST 请求,这将在墙上添加一个帖子
    • 8
  4. Andrew_STOP_RU_AGRESSION_IN_UA
    2020-12-31T05:09:08Z2020-12-31T05:09:08Z

    这完全取决于您的需求和网站:

    • 网站上是否使用AJAX
    • 是否有像 Re-Capcha 这样难以绕过的验证码
    • 需要多复杂的一系列操作
    • 速度有多重要
    • 页面将加载多长时间(可以只是一个页面,也可以是无限滚动)
    • 您需要跨平台解决方案吗
    • 像 CORS 这样的网站上是否使用了任何棘手的技术

    原则上,如果我们总结下面提供的所有信息并得出最普遍的答案:

    一个。如果您需要最快的“一次性”解决方案并且速度并不重要 - 那么 Selenium

    b. 如果是测试任务 - Selenium

    在。如果您需要一个通用的解决方案和最简单的长期支持,无论编码需要多长时间:

    1. CefSharp 用于传递验证码/重新验证码(如果没有则删除该项目)
    2. 从 CefSharp 中提取 cookie,将它们粘贴到 dotnet cookie 中
    3. 然后通过 HttpWebRequest 请求与站点交互

    如果您只需要解析数据 - AngleSharp。没有 htmlAgrilityPack。


    有关每种方法的更多详细信息....


    网页浏览器

    减

    • 管理很差。工作困难。
    • 图形元素,这意味着它会吃掉 RAM 并且工作缓慢
    • 不适用于无限页面
    • 超曲线与 JS 一起工作。有些网站就是不显示。过时的工具。

    优点

    +?理论上可以跨平台,但不确定。


    直接通过 HttpWebRequest Post/Get 请求进行后续解析。所需的序列可以在浏览器开发人员控制台的“网络”选项卡上找到。建议不要使用低级请求,而是使用一些用于 REST 请求的库。写代码会快很多。

    减

    • 如果该网站是 AJAX - 可能很难像那样工作。
    • 没办法通过 Re-Capcha。原则上可能很难通过验证码。

    优点

    • 如果站点频繁更改,代码将不会经常出错(前端不如后端稳定,因此是与后端交互的理想解决方案!)
    • 最高性能。您可以并行运行数千个页面。
    • 可以处理任何大小的“无限”页面。【虽然会流汗】
    • 优秀的跨平台代码

    Selenium - 一般来说,它是专门为网站的自动化测试而设计的。包括 Ajax 技术。也就是说,它几乎可以完成人们在浏览器中可以执行的所有操作:查找网站界面元素、向其发送按钮点击、滚动、截屏、检查可见性/可访问性等。因为 指定了 C# 标签,也有人说没有额外的窗口,你需要使用一堆:Selenium Web-Driver 和 PhantomJS。Phantom 是一款基于类 chrome 引擎的无 UI 浏览器。它可以像一个简单的浏览器一样做所有事情,只是它不在视觉上显示并且不在渲染上浪费资源。减

    • 它不是 OOP,而且使用起来很笨拙。
    • 大页面效果很差
    • 非常慢
    • нужно использовать сторонние браузеры и в проэкт качать доп.библиотеки для поддержки нужного браузера
    • Не умеет работать с внешними окнами. Например с системным окном аутентификации на сервер (с версии 3.4 умеет). Или с окнами Open/Save file (для этого есть костыли а так же я написал полууниверсальное решение: https://github.com/ukushu/DialogCapabilities )

    Плюсы

    • На нем вполне можно проходить ReCapcha. При помощи юзера, правда :)
    • Можно пройти и без юзера, если ипользовать аудиокапчу + распознавание текста с аудио через googleAPI. Например, вот здесь есть реализация прохождения рекапчи ботом, но на питоне: https://github.com/eastee/rebreakcaptcha/blob/master/rebreakcaptcha.py
    • Вполне может работать с AJAX. А если допилять костыли, то, даже, вполне неплохо работать.
    • Работает с посделовательностями действий любой сложности. В том числе всякие драг енд дропы.
    • Может запускатся на многих компьютерах в паралели

    Не уверен

    ? понятия не имею по поводу кросплатформенности


    Оболочки вокруг готового движка вроде Хромиума. За пример - CefSharp.

    Минуса

    • хреново работает с большими/бесконечными страницами
    • относительно медленный
    • нужно качать несколько библиотек
    • многий функционал доступный с коробки в селениуме нужно будет реализовывать самому через JS код.

    Плюса

    • На нем вполне можно проходить ReCapcha. При помощи юзера, правда :)
    • работает с AJAX
    • Работает с посделовательностями действий любой сложности
    • Умеет работать с внешними окнами. Например с системным окном аутентификации на сервер.

    Не уверен:

    ? понятия не имею по поводу кросплатформенности. Скорее всего есть


    AngleSharp 是一个很棒的东西,但它专为解析而设计。他出色地完成了自己的任务。

    • 6
  5. Владимир Александров
    2020-12-25T04:46:43Z2020-12-25T04:46:43Z

    指定如何处理在站点字段中输入的文本?该站点是否发送 GET/POST 或以不同方式处理它?

    我将对 googl 和 GET 的示例给出我的想法。如果我们可以直接发送请求、获取结果并进一步解析,为什么我们需要模拟网站上的用户操作

    string query_user = Console.ReadLine();
    string url = "https://www.google.ru/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#newwindow=1&q=" + query_user;
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    

    然后我们从变量中提取response所需的一切

    • 5
  6. Гончаров Александр
    2020-12-30T08:12:08Z2020-12-30T08:12:08Z

    问题的标题是控制台应用程序。但是,我可以从文本中猜到

    您需要向该字段发送一些值,单击按钮,然后获得一个新页面,您可以在其中转到第一个链接。

    也许在浏览器中模拟用户操作适合您。关于浏览器中的仿真:

    通过编写您自己的浏览器扩展(例如 Firefox/GoogleChrome)可以非常准确地模拟用户操作——这与真实用户没有区别。该插件可以完全拦截控制——例如,打开带有特定站点的选项卡,并“捕获”它。

    在插件内部,正在开发一个特定的实体,它可以模拟鼠标移动和对象之间的点击:选择来自另一个站点的对象本身,例如,使用简单的 jQuery - 就像在任何站点的代码中一样。此外,实体需要添加在任何字段中模拟文本输入的能力。

    可以通过发送受信任的 DOM 事件(插件中的代码可以做到这一点)来完成模拟,或者您可以直接使用 WinApi 及其 PostMessageW(至少 Firefox 插件可以连接任何 dll,然后从 JS 使用它)——一种钢筋混凝土方法。一般来说,从技术上讲,这样的模拟器是无法与用户区分开来的。

    著名的插件Greasemonkey 因此类活动而入狱 。但是如果仿真的规模很大(在某些页面添加某些脚本的策略是不够的),我不推荐它,因为它的逻辑不够。

    如果您需要从控制台向仿真添加浏览器控件,请使用 selenium。如果您希望它全部从标准服务器运行(即没有 GUI),这将不起作用。但在我的实践中,我会说我们经常使用模拟器,因为我们有单独的服务器和 Windows,带有 GUI。没有 GUI,只有一个控制台,有人认为高质量的仿真是行不通的。

    此类模拟器的经典用途是解析器机器人、垃圾邮件发送者机器人、游戏机器人、您自己站点的自动测试。

    • 3
  7. Anatol
    2020-01-27T12:50:01Z2020-01-27T12:50:01Z

    等待。

    等待功能

    • 轻松自动化所有主要 HTML 元素
    • 按多个属性查找元素
    • 对页面和控件模型的原生支持
    • 支持AJAX网站测试
    • 支持创建网页截图
    • 支持框架(跨域)和 iframe
    • 处理弹出对话框,如警报、确认、登录等。
    • 支持 HTML 对话框(模态和非模态)
    • 易于与您最喜欢的(单元)测试工具集成
    • 适用于 Internet Explorer 6、7、8、9 和 FireFox 2 和 3
    • 可以与任何 .Net 语言一起使用
    • 根据 Apache License 2.0 获得许可
    • 下载超过 120.000 次
    • 由于它是开源的,您可以自己添加和贡献新功能

    例子:

    [Test] 
    public void SearchForWatiNOnGoogle()
    {
      using (var browser = new IE("http://www.google.com"))
      {
        browser.TextField(Find.ByName("q")).TypeText("WatiN");
        browser.Button(Find.ByName("btnG")).Click();
      
        Assert.IsTrue(browser.ContainsText("WatiN"));
      }
    }
    
    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5