Как нажать программно кнопку на другом сайте на C#

Добрый день.

Разберем такой случай когда нам присылают ссылку на подтверждение, а после перехода по ссылке открывается страница с кнопкой подтверждения на которую надо нажать. Либо просто надо нажать на кнопку на странице HTML. Если с переходом по ссылке более менее все понятно, то с нажатием кнопки довольно не просто. Давайте разбираться.

 

Немного теории.

Обычно копка является частью HTML формы. Соответственно нажимая на кнопку браузер формирует ответ серверу, обычно в POST запросе, собирая все данные с  input элементов в веб-формы.  Проще говоря цель нажатия кнопки это отослать представлениt заполненной веб-формы на веб-сервер.

 

Возьмем следующий пример:

 <form method="POST" name="login" action="Home/Result">
            <input type="hidden" name="id" value="id">
            <input type="hidden" name="sitename" value="deptech">
            <input type="submit" name="send" class="submit">
        </form>

В этом примере имеется форма с именем  «login» методом «POST» и обработчиком «Home/Result». И имеются поля  id и sitename которые уже заполнены значениями id и deptech соответственно, также имеется кнопка с именем «send».

В итоге нужно сформировать представление веб формы отослать на обработчик «Home/Result».

По умолчанию интернет-тип данных для отправки вэб-форм медиа это: «application/x-www-form-urlencoded».

Это формат для кодирования пар ключ-значение с возможностью дублирования ключей. Каждая пара ключ-значение отделяется символом &, ключ отделён от значения символом = . В ключах и значениях пробелы заменяются на знак +, и затем, используя URL-кодирование, заменяются все не буквенно-цифровые символы.

 

Для нашего примера :

Id: id

sitename: deptech

 

Будет закодирована следующим образом

Id=id&sitename=deptech

 

WebClient нам в помощь.

 

Так как мы работаем на прямую с протоколом то этот ответ мы должны сформировать самостоятельно.

Открываем проект в VisualStudio, создаем проект под названием, например, ClickHtmlButton.   Кидаем на форму три текстбокса и кнопку.

форма

В первый текстбокс будем подставлять нашу ссылку, во второй будем обозначим как имя нашей html кнопки. Ну и третье поле будем записывать ответ сервера после нажатия htmlкнопки.

В обработчик кнопки добавим следующий код:

 private void button1_Click(object sender, EventArgs e)
        {
            string htmlLink = textBox1.Text;
            string htmlButtonName = textBox2.Text;
            ButtonClicker buttonClicker = new ButtonClicker();
            string responseHtml = buttonClicker.ButtonClick(htmlLink, htmlButtonName);
            textBox3.Text = responseHtml;

        }

Установка HTMLAgilityPack

Для решения проблемы нам понадобиться также дополнение HTML Agility Pack это HTML парсер. Его можно найти в Nuget через поиск либо добавить через ту же консоль nuget командой:

Install-Package HtmlAgilityPack. 

Потом в класс добавим

using hap= HtmlAgilityPack;

Добавим два класса которые будут описывать нашу форму и поля ввода


public class Inputitem
{
/// <summary>
/// Тип элемента формы
/// </summary>
public string InputType { get; set; }
/// <summary>
/// Имя элемента формы
/// </summary>
public string InputName { get; set; }
/// <summary>
/// Значение элемента формы
/// </summary>
public string InputValue { get; set; }
/// <summary>
/// Форма в которой содержатся элементы
/// </summary>
public HtmlFormValue FormAtribute { get; set; }
}

Класс который будет описывать нашу форму


public class HtmlFormValue
{
public HtmlFormValue()
{
ListInputs = new List<Inputitem>();
}
/// <summary>
/// Имя вебформы, может отсутствовать
/// </summary>
public string NameForm { get; set; }
/// <summary>
/// Oбработчик, к которому обращаются данные формы при их отправке на сервер
/// </summary>
public string ActionForm { get; set; }
/// <summary>
/// Метод который использует форма для отправки на сервер Post или Get
/// </summary>
public string MethodForm { get; set; }
/// <summary>
/// Список всех всех input Html элементов в вебформе
/// </summary>
public List<Inputitem> ListInputs { get; set; }
/// <summary>
/// Список элементов в формате 'Имя=Значение'
/// </summary>
/// <returns></returns>
public List<string> GetInputsNameValue()=>ListInputs
.Select(x=>$"{x.InputName}={x.InputValue}")
.ToList();
}

 

Добавим недостающий класс ButtonClicker в проект.

using System.Net;
using System;
using hap = HtmlAgilityPack;
using System.Collections.Generic;
using System.Linq;
 
namespace ClickHtmlButton
{
   public class ButtonClicker
    {
        public string ButtonClick(string URI, string ButtonValue)
        {
 
 
            Uri uri = new Uri(URI);
 
            using (WebClient wc = new WebClient())
            {
 
               //Загружаем страницу HTML в string
                string HtmlString = wc.DownloadString(uri);
 
 
                //Создаем HtmlAgilityPack
                hap.HtmlDocument HtmlDoc = new hap.HtmlDocument();
 
                //Загружаем Html документ из строки
                HtmlDoc.LoadHtml(HtmlString);
 
                //Выбираем все формы на странице
                hap.HtmlNodeCollection formNodes = HtmlDoc.DocumentNode.SelectNodes("//form");
              
                List<HtmlFormValue> HtmlForms = new List<HtmlFormValue>();
                var AllInputs = new List<Inputitem>();
                if (formNodes != null)
                {
                    foreach (var formAtribute in formNodes)
                    {
 
                        HtmlFormValue FormAtribute = new HtmlFormValue
                        {
                            ActionForm = formAtribute.Attributes["action"].Value,
                            MethodForm = formAtribute.Attributes["method"].Value,
                            NameForm = formAtribute.Attributes["name"].Value
                        };
 
                        //Выбираем все imputs на форме
                        hap.HtmlNodeCollection inputsNodes = formAtribute?.SelectNodes("//input");
 
                        if (inputsNodes != null)
                        {
                            AllInputs = inputsNodes
                                .Select(x => new Inputitem
                                {
                                    InputName = x.Attributes["name"]?.Value ?? "",
                                    InputType = x.Attributes["type"].Value,
                                    InputValue = x.Attributes["value"]?.Value ?? "",
                                     FormAtribute = FormAtribute
                                }
                         ).ToList();
                        }
                        FormAtribute.ListInputs = AllInputs;
                        HtmlForms.Add(FormAtribute);
                    }
 
                 
                    HtmlFormValue FindForm = AllInputs.First(x => x.InputName == ButtonValue).FormAtribute;
 
 
                    if (FindForm != null)
                    {
                       //Собираем запрос
                       //Указываем способ кодировки
                        wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                        //добавляем параметры
                        string myParameters = string.Join("&", FindForm.GetInputsNameValue());
                        //Формируем строку на указанный ресурс
                        string uripath = $"{uri.AbsoluteUri}{FindForm.ActionForm}";
                        //отправляем и получаем результат
                        string HtmlResult = wc.UploadString(uripath, myParameters);
                        return HtmlResult;
                    }
                    else { return ""; }
 
                }
                else
                {
 
                    return "";
                }
            }
        }
    }
}

Для тестов будем использовать нашу форму.

 

 <form method="POST" name="login" action="Home/Result">
            <input type="hidden" name="id" value="id">
            <input type="hidden" name="sitename" value="deptech">
            <input type="submit" name="send" class="submit">
        </form>

Запускаем и тестим:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*