Очистка определенных c фрагментов данных с веб-сайта в C# с использованием HtmlAgilityPack - PullRequest
1 голос
/ 04 августа 2020

Я пытаюсь использовать HtmlAgilityPack для очистки веб-страницы для определенного вложенного класса div, который содержит тег span с данными, которые я хочу извлечь

Полный XPath для текста элемента, который я хочу:

/html/body/div[2]/div/div[1]/div/table/tbody/tr/td/span

Мой код:

  static void Main(string[] args)
        {
            HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
            HtmlAgilityPack.HtmlDocument doc = web.Load("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph");

            var paragraph = doc.DocumentNode.SelectNodes("//div[@class='mainBody']//div[@class='content']//div[@class='resultContainer']" +
                "//div[@class='resultBox']//table[@class='paragraphResult']").ToList();

            foreach (var item in paragraph)
            {
                Console.WriteLine(item.InnerText);
            }
        }

Я пробовал поместить полный XPath в doc.DocumentNode.SelectNodes(), а также только Xpath, который равен //*[@id='result'] Моя проблема в том, что он либо возвращает ничего, или я получаю сообщение об ошибке: Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source') в строке doc.DocumentNode.SelectNodes() .

1 Ответ

1 голос
/ 04 августа 2020

Источник проблемы в том, что Paragraph загружается через AJAX, JS скриптом после загрузки страницы. Если вы откроете Dev Tools / Network в браузере, вы увидите это.

Загруженная часть страницы выглядит так

<table class="paragraphResult">
    <tr>
        <td>
            <span id="result"></span>
        </td>
    </tr>
</table>

Внутри ничего нет.

И после load, страница отправляет запрос AJAX POST на тот же URL-адрес и получает простую строку с параметрами

Subject1: "",
Subject2: ""

И как это выглядит в формате URL-Encoded

Subject1=&Subject2=

To выполнить эмуляцию поведения формы, вы можете отправить запрос POST вручную. HtmlAgilityPack здесь бесполезен, потому что полученные данные представляют собой простую строку.

class Program
{
    private static readonly HttpClient client = new HttpClient();

    static async Task Main(string[] args)
    {
        Console.Write("Proper Noun 1: ");
        string subject1 = Console.ReadLine();
        Console.Write("Proper Noun 2: ");
        string subject2 = Console.ReadLine();
        Dictionary<string, string> parameters = new Dictionary<string, string>()
        {
            { "Subject1", subject1 },
            { "Subject2", subject2 }
        };
        try
        {
            string result = await PostHTTPRequestAsync("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph", parameters);
            Console.WriteLine(result);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

    private static async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
    {
        using (HttpContent formContent = new FormUrlEncodedContent(data))
        using (HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
    }
}

Вывод в консоль

Proper Noun 1: test
Proper Noun 2: StackOverflow
When will the bass garage StackOverflow? A digest sighs test below the objective card. Why won't test finish behind a girlfriend? A heating science approaches test.

Работает хорошо. Все, что вам нужно для этого, - это правильно анализировать HTTP-трафик c в браузере. Также HttpClient - мощный инструмент для взаимодействия с Интернетом.

...