Создание метода на C#, который обходит HTML-документ и извлекает контент на основе запроса, т.е. Custom HTML Crawler.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Создание метода на C#, который обходит HTML-документ и извлекает контент на основе запроса, т.е. Custom HTML Crawler.

Сообщение Anonymous »

Я создал программу, которая анализирует каждый элемент HTML-документа. Он сохраняет его в структуре дерева (несбалансированное дерево).

Код: Выделить всё

public class Attribute
{
public string? Key { get; set; }
public string? Value { get; set; }
public Attribute() {}
public Attribute(string key, string value)
{
this.Key = key;
this.Value = value;
}
}
public class Node
{
public string Tag { get; set; }
public string Content { get; set; }
public List[url=http://https://www.w3schools.com]w3schools[/url]
[img]img_girl.bmp[/img]


Программа должна извлекать контент из HTML-документа на основе запросов:
(Это все вводимые пользователем данные в Консоли)
  • PRINT // — извлекает все текстовое содержимое документа.
  • PRINT // html/body/p -> Выходы: «Text1», «Text2», «Text3»
  • PRINT //html /body/table/tr/td -> Выходы: «11», «22», «33», «44»
  • PRINT //html/body/p[2] -> Выходы: «Text2»;
  • PRINT / /html/body/*[@id='table2'] -> Выходы: "33", "44"
  • PRINT //html/body/p[@id='p3'] -> извежда: 'Text3'.
  • PRINT //html/body/table[@id='table2']/tr[2]/td -> извежда: "44"
По сути, программа должна представлять собой более простую версию XPath.
Это моя функция обхода:

Код: Выделить всё

private List Traverse(Node node, string[] segments, int index)
{

List matches = new List();
if (node == null) return matches;

if (index + 1 >= segments.Length)
{
if (!string.IsNullOrEmpty(node.Content))
{
matches.Add(node.Content);
}
foreach (Node child in node.Children)
{
matches.AddRange(Traverse(child, segments, index));
}
return matches;
}
string segment = segments[index];

if (segment.Contains("*"))
{
foreach (var child in node.Children)
{
matches.AddRange(Traverse(child, segments, index + 1));
}
}
else if (segment.Contains("@"))
{
int attributeStart = segment.IndexOf('@');
int attributeEnd = segment.IndexOf('=');
if (attributeStart != -1 && attributeEnd != -1)
{
string attributeName = segment.Substring(attributeStart + 1, attributeEnd - attributeStart - 1);
string attributeValue = segment.Substring(attributeEnd + 2, segment.Length - attributeEnd - 4);

foreach (var child in node.Children)
{
if (child.Attributes.Any(attr => attr.Key == attributeName && attr.Value == attributeValue))
{
matches.AddRange(Traverse(child, segments, index + 1));
}
}
}
else
{
Console.WriteLine("Invalid attribute format");
}
}
else if (segment.Contains("["))
{
int indexStart = segment.IndexOf("[");
int indexEnd = segment.IndexOf("]");
if (indexStart != -1 && indexEnd != -1)
{
string indexValue = segment.Substring(indexStart + 1, indexEnd - indexStart - 1);
if (int.TryParse(indexValue, out int indexNum))
{
if (indexNum >= 0 && indexNum <  node.Children.Count)
{
matches.AddRange(Traverse(node.Children[indexNum], segments, index + 1));
}
else
{
Console.WriteLine($"Invalid index: {indexNum}");
}
}
else
{
Console.WriteLine($"Invalid index value: {indexValue}");
}
}
else
{
Console.WriteLine("Invalid index format");
}
}
else
{
foreach (var child in node.Children)
{

if (segments[index + 1] == child.Tag)
{
matches.AddRange(Traverse(child, segments, index + 1));
}
}
}
return matches;
}
Поэтому в последнем операторе else раньше было сегмент вместо сегментов[index + 1]:

Код: Выделить всё

//...
foreach (var child in node.Children)
{
if (segments[index + 1] == child.Tag)
{
matches.AddRange(Traverse(child, segments, index + 1));
}
}
//...
Это изменение устранило проблему, когда я пишу //html/body, и он ничего не выводит, хотя должен выводить все текстовое содержимое тела.
Но теперь, делая это таким образом, я могу искать определенные элементы, такие как //html/body/p[1].
Когда функция достигает оператора else и проходит через дочерние элементы узла (

Код: Выделить всё

node.Children)
segments[index + 1]
на самом деле не равен дочернему узлу Node, поэтому следующий уровень не проходит должным образом.
Затем выходит из цикла foreach и возвращаются совпадения. выполняется без содержимого.
Если кто-то сможет понять мою логику и помочь мне решить проблему.

Подробнее здесь: https://stackoverflow.com/questions/781 ... -content-b
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • PHP cURL – Как проверить, получает ли Google Crawler правильный файл robots.txt
    Anonymous » » в форуме Php
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous
  • Symfony Dom Crawler Array Push Each
    Anonymous » » в форуме Php
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • Можно ли запустить приложение Crawler по конкретной деятельности приложения?
    Anonymous » » в форуме Android
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous
  • Разница между BeautifulSoup и Scrapy Crawler?
    Anonymous » » в форуме Python
    0 Ответы
    3 Просмотры
    Последнее сообщение Anonymous
  • Будет ли передача HTML -ссылка на Custom Cust Custom Clock, если крюк будет много работает? [дублировать]
    Anonymous » » в форуме Javascript
    0 Ответы
    7 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»