Suppose there is a site on which there is a field.

In this field, you need to send some value, click on the button, then get a new page, where to go on the first link.

Do I need to refer to the WebBrowser class for these?

If possible, show an example (for example, you can take the target google site, but without using its API.)

  • Do I need to fill out forms from the application and follow the links on the pages of any site? - LukavskyM
  • @ demol0cv, Yes, exactly. - iluxa1810
  • Are you sure you need to do this from your application? For example, Firefox has some very powerful add-ons for solving such problems, for example Greasemonkey and iMacros. - LukavskyM
  • @ demol0cv, yes, I need to parse it all later. - iluxa1810
  • Googly headless browsers - Herrgott

7 answers 7

Google in the console

Let me show you by the example of a program that allows you to google directly in the console (it extracts the first title links of the search on google.com ):

Preliminary work

Use CefSharp - a wrapper library based on Chromium. Described it in great detail in this answer . It is installed simply through the Nuget package.

 Install-Package CefSharp.OffScreen -Version 57.0.0 

CefSharpWrapper two classes from my answer ( CefSharpWrapper and ConvertHelper ), you have a skeleton program ready with which you can execute any JavaScript directly from the console application.


Also install x64 or x86 as a platform. Any CPU platform is supported, but requires additional code .

Additional properties and methods

Also for this task, add the Address property to CefSharpWrapper :

 public string Address => _browser.Address; 

and the WaitTillAddressChanges method:

 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(); } 

An example of the program itself

Here is an example of the program itself ( Program class, Main method):

 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(); } } 

Program results

For example, if I enter "parse html C #":

Program results


AJAX

It is also quite convenient to work with AJAX using this library .

  • Updated the program. Added a demonstration of how to google right in the console. - Vadim Ovchinnikov
  • Who is minus? What's wrong? - Vadim Ovchinnikov
  • one
    Someone minus it, it happens, shit happens. Do not worry. :) - Nick Volynkin

If you only need to code some specific, known parts of a website, you can simply pull out the necessary requests that are sent by the browser (you can isolate them in the browser developer console, usually on the Network tab) and send this request in the program, for example via HttpClient .

If you cannot know the initial requests themselves (it is necessary to receive dynamically in the program itself), then there can be 2 variants of events:

  1. If the site can work without using ajax - parse the page for the presence of the <form> and build on it. It has an action attribute that contains a path and an encoded attribute, which specifies the encoding format (if not, the default is " application/x-www-form-urlencoded ", it seems, although it’s definitely better to look through the developer console). All this is collected, including the parameters inside the <form> , sent via the HttpClient and get an answer
  2. If the site works only through ajax - it’s already more difficult and there’s no other way out except to manually look through the Network which requests are being formed and I don’t see them in code

But in most cases, there is enough the usual sending of pre-prepared (subtracted) requests with their own parameters.

You can also bind to HttpClient 'from HttpClientHandler for storing cookies and other buns.

For example, you need to add a post on the wall in VK for a certain time - the algorithm will be like this:

  1. Create an HttpClient with HttpClient with it
  2. Send through POST request to the desired address (you can see on the page VC in the source code or isolate through the developer console) with your username and password as values. This request will return an answer, but in this case it is not needed, just wait for the HttpResponseMessage to come so that we have a cookie
  3. Send another POST request that will add a message to the wall
  • vk has built-in timer for postponed posts - mymedia
  • Very good answer. One has only to add that if the sites use captcha like Google ReCapcha. here, without options, browser engines are needed ... - Andrew

I found an interesting lib of Selenium with the help of which, through the driver, you can interact with a real browser. Pretty easy to manage:

 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); } } } 

However, I still wanted to know how to do this using standard .NET tools.

  • 2
    In the standard .NET there is no built-in browser, the more capable of running JS. Any solution involves an external browser - IE in the form of WebBrowser Control, or some other when using selenium. If you don’t want the browser to actually open and show up on the screen - take selenium + phantomjs - PashaPash
  • @PashaPash, for some reason, phantomjs fell on me because I swallowed Chrome. - iluxa1810
  • @PashaPash I have a question about this code var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(d => d.Title.StartsWith("cheese", StringComparison.OrdinalIgnoreCase)); var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); wait.Until(d => d.Title.StartsWith("cheese", StringComparison.OrdinalIgnoreCase)); . I understand he waits 10 seconds until the page loads. Is there a more elegant way to not guess the interval? So that it was a method that waits for as long as necessary without specifying an interval, or just some kind of event like AddressChanged ? - Vadim Ovchinnikov
  • @VadimOvchinnikov, as I understand it, in fact, you do not need to explicitly set the wait. After the test on chrome, I noticed that the driver waits for the page to load and after that the following instructions are followed. - iluxa1810

Specify how the processing of the entered text in the field on the site? Does the site send it GET / POST or process it differently?

I will give the course of my thoughts on the example of googl'a and GET .. Why should we emulate user actions on the site if we can directly work with sending a request, obtaining a result and further parsing

 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(); 

And then we extract from the response variable all that is needed.

  • You can of course curl .. | grep ... curl .. | grep ... juzat from the console and that's it. But this is a crutch - i. will break down if the site they are trying to manage changes a little. And it will not work at all if human-like emulation is required - for example, if it is required that the site cannot distinguish a robot from a human. Also this is not applicable if the emulator is needed for auto-testing the site UI. - Goncharov Alexander
  • @GoncharovAleksandr for autotests UI there are whole frameworks like Selenium, there is no need to invent anything. - Nick Volynkin
  • @Nick Volynkin, Selenium is only a library for controlling the browser from different applications, of course you can write tests with it. But why control the browser from somewhere, if it can be done from the inside. In Selenium there is of course a recorder that reduces the time for writing simple tests - but you can’t do complicated sequential manipulations. - Goncharov Alexander
  • Emulation of user actions is necessary in cases where you cannot do something through requests. For example, go through Google's captcha :) - Andrew
  • @GoncharovAleksandr judging by the written, you only know SeleniumIDE. In practice, Selenium basically means Selenium WebDriver, with the help of which complex sequential manipulations are written. Of course, he, in turn, is framed in a special wrapper framework written for a specific site. - Andrew

It all depends on your needs and on the site:

  • Is AJAX used on the site?
  • Are there hard-to-go captcha like re-capcha
  • How complex is the sequence of actions needed.
  • How important is speed
  • How long the page will be loaded (this may be just a page, or maybe endless scrolling)
  • Do you need cross-platform solutions?
  • Are any tricky technologies used on sites like CORS

In principle, if we summarize all the information submitted below and lead to the most universal answer:

but. if you need the fastest "one-time" solution and the speed of work is not important - it means Selenium

b. If this is a testing task - Selenium

at. If you need a universality of the solution and the most simple support for long periods of time and no matter how much coding will take:

  1. CefSharp for captcha / recaptcha
  2. pull cookies out of CefSharp, stick them into the dotnet cookies
  3. and then interact with the site via HttpWebRequest requests

More about each of the ways ....


Webbrowser

Minus

  • Very poor management. Difficult to work with.
  • graphic element, which means it will eat operatives and work slowly
  • does not work with endless pages
  • Hyper curve work with js. Some sites are simply not displayed. Outdated tool.

Plus

+? in theory, cross-platform, but not sure.


Direct work through HttpWebRequest Post / Get requests with the subsequent parsing. The required sequence can be found in the browser developer console, on the Network tab. It is advisable to use NOT low-level requests and some libraries for REST requests. It will be faster much the code.

Minus

  • if on an AJAX website, it can be difficult to work.
  • no way to go through re-capcha. It may be difficult to pass the captcha in principle.

Plus

  • if the site changes frequently, the code will be less often (the frontend is less stable than the backend, so an ideal solution for interacting with the backend!)
  • The highest speed. You can at least a thousand pages in parallel.
  • Can work with "infinite" pages of any size. [Although this will need to sweat a little]
  • excellent cross-platform code

Selenium - in general, it is designed specifically for automated testing of websites. Including with ajaks-technology. That is, it can do almost all the actions that people can do in the browser: finding the interface elements of the site, sending them button presses, scrolling, taking screenshots, checking for visibility / accessibility, etc. Because specified C # tag, as well as it was said about the absence of unnecessary windows, you need to use a bunch: Selenium Web-Driver and PhantomJS. Phantom is a bezayayny browser on the engine like a chrome. It can all the same as a simple browser, only it does not show visually and does not spend resources on rendering. Separately, I want to say that the selenium itself is rather inconvenient and far from the PLO. The problem is that there is no particular choice ...

Minus

  • He is not pretty and pretty crooked to use.
  • very bad work with large pages
  • very slow
  • you need to use third-party browsers and download additional libraries in the project to support the desired browser
  • Can not work with external windows. For example, with the system window authentication to the server (from version 3.4 is able). Or with the Open / Save file windows (there are crutches for this as well as I wrote a semi-universal solution: https://github.com/ukushu/DialogCapabilities )

Plus

  • It is quite possible to pass ReCapcha. With the help of the user, it is true :) And if confuses, then without the help of the user. For example, here is the implementation of the passage by the bot: https://github.com/eastee/rebreakcaptcha/blob/master/rebreakcaptcha.py
  • It may well work with AJAX. And if you finish crutches, then, even, it is quite good to work.
  • Works with actions of any complexity. Including all kinds of drag and drop drops.
  • Can run on many computers in parallel

Not sure

? I have no idea about cross-platform


The shell around the finished engine like Chromium. For example - CefSharp.

Minus

  • sucks on large / endless pages
  • relatively slow
  • need to download several libraries
  • Many features available from the box in Selenium will need to be implemented by the JS code itself.

Plus

  • It is quite possible to pass ReCapcha. With the help of the user, really :)
  • works with AJAX
  • Works with actions of any complexity.
  • Able to work with external windows. For example, with the system authentication window on the server.

Not sure:

? I have no idea about cross-platform. Most likely there

    In the title of the question is a console application. But, I can assume the text

    In this field, you need to send some value, click on the button, then get a new page, where to go on the first link.

    Perhaps you will suit the emulation of user actions in the browser. About browser emulation:

    Very accurate emulation of user actions is done by writing your own browser extension (Firefox / GoogleChrome for example) - not to distinguish from this user. A plugin can completely take over control - for example, open a tab with a specific site, and "grab" it.

    Inside the plugin, a certain entity is developed that can emulate movement and mouse clicks from object to object: objects themselves from another site are selected, for example, by simple jQuery - just like in the code of any site. Entities also need to add the ability to emulate text input in any field.

    Emulation can occur by sending a trusted DOM event (it can do the plug-in code), or you can directly use WinApi and its PostMessageW (at least firefox add-ons can connect any dll and then use it from JS) —the reinforced concrete method. In general, technically, such an emulator cannot be distinguished from the user.

    Under similar activity the known Greasemonkey addon is ground . But if the scale of the emulation is planned large (the policy of adding certain scripts to certain pages is not enough), I would not recommend it, because its logic is not enough.

    If you want to add emulation and browser control from the console, use selenium. It does not work if you want it to work from a standard server - that is, without a GUI. But in my practice I will say - they used emulators often, for them we had separate servers with Windows, with GUI. Without a GUI, with a bare console, there is an opinion that it will not work to emulate quality ..

    The classic use of such emulators is bots-parsers, bots-spammers, bots-gaming, auto-testing your own site.

      In my opinion, the best solution is WatiN .

      WatiN Features

      • Automate all major HTML elements with ease
      • Find elements by multiple attributes
      • Native support for Page and Control model
      • Supports AJAX website testing
      • Supports creating screenshots of webpages
      • Supports frames (cross domain) and iframes
      • Handles popup dialogs like alert, confirm, login etc ..
      • Supports HTML dialogs (modal and modeless)
      • Easy to integrate with your favorit (unit) test tool
      • Works with Internet Explorer 6, 7, 8, 9 and FireFox 2 and 3
      • Can be used with any .Net Language
      • Licensed under the Apache License 2.0
      • Downloaded more than 120,000 times
      • New features yourself

      Example:

       [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")); } } 

      I myself use for grabbing.

      • Judging by the dead domain, his support is not very good .... Better is selenium, since it is so ... - Andrew