Win32.: Как очистить HTML без регулярных выражений?
Недавняя говорит, что вы никогда не должны анализировать HTML с использованием регулярных выражений, но не дает альтернативы.
Я хочу скопировать результаты поиска, извлекая значения:
<div class="used_result_container">
...
...
<div class="vehicleInfo">
...
...
<div class="makemodeltrim">
...
<a class="carlink" href="[Url]">[MakeAndModel]</a>
...
</div>
<div class="kilometers">[Kilometers]</div>
<div class="price">[Price]</div>
<div class="location">
<span class='locationText'>Location:</span>[Location]
</div>
...
...
</div>
...
...
</div>
...and it repeats
Вы можете увидеть значения, которые я хочу извлечь, [заключенные в скобки]:
- Url
- MakeAndModel
- Километры
- Цена
- Местоположение
Предполагая, что принять предположение о том, что синтаксический анализ HTML:
Каким образом это сделать?
Предположения:
- родной Win32
- свободный html
Условные разъяснения:
Native Win32
- .NET/CLR не является родным Win32
- Java не является родным Win32
- perl, python, ruby не являются родными Win32
- предположим, что С++ в Visual Studio 2000 скомпилирован в собственное приложение Win32
Встроенные программы Win32 могут вызывать библиотеку вызовов:
- скопированный исходный код
- DLL, содержащие точки входа функции
- DLL, содержащие COM-объекты
- DLL, содержащие COM-объекты, которые являются COM-вызываемыми оболочками (CCW) вокруг управляемых объектов .NET
Свободный HTML
- xml не является свободным HTML
- xhtml не является свободным HTML
- строгий HTML не потерян HTML
Loose HTML подразумевает, что HTML не является корректным xml (строгий HTML не является хорошо сформированным xml в любом случае), и поэтому синтаксический анализатор XML не может быть использован. На самом деле я присутствовал в предположении, что любой HTML-парсер должен быть щедрым в HTML, который он принимает.
Разъяснение # 2
Предполагая вам нравится идея превратить HTML в объектную модель документа (DOM), как же вы получаете доступ к повторяющимся структурам данных? Как бы вы шли по дереву DOM? Мне нужен DIV node, который является классом used_result_container, у которого есть дочерний DIV класса VehicleInfo. Но узлы необязательно должны быть прямыми детьми друг друга.
Похоже, я торгую одним набором проблем с регулярными выражениями для другого. Если они изменят структуру HTML, мне придется переписать мой код для соответствия - как и с регулярными выражениями. И если мы хотим избежать этих проблем, потому что это проблемы с регулярными выражениями, что я делаю вместо этого?
И я не буду писать парсер регулярных выражений для узлов DOM? Я пишу движок для синтаксического анализа строки объектов, используя внутренний конечный автомат и перехват вперед и назад. Нет, должен быть лучший способ - так, как Джефф намекнул.
я намеренно держал исходный вопрос неопределенным, чтобы не приводить людей к неправильному пути. я не хотел подразумевать, что решение, обязательно, имело какое-либо отношение к:
- прохождение дерева DOM
- запросы xpath
Разъяснение # 3
Образец HTML я при условии, что я обрезана до важных элементов и атрибутов. Механизм, который я использовал для обрезания HTML, основывался на моем внутреннем уклоне, который использует регулярные выражения. Я, естественно, думаю, что мне нужны разные " sign-posts в HTML, которые я ищу.
Поэтому не путайте представленный HTML для всего HTML. Возможно, какое-то другое решение зависит от наличия всего исходного HTML.
Обновление 4
Единственные реквизиты, по-видимому, связаны с использованием библиотеки для преобразования HTML в объектную модель документа (DOM). Тогда вопрос должен был бы стать: , а затем?
Теперь, когда у меня есть DOM, что мне с ним делать? Кажется, что мне все еще нужно ходить по дереву с помощью некоторого регулярного парсера выражения DOM, способного к прямому совпадению и захвату.
В этом конкретном случае мне нужны все узлы used_result_container DIV, которые содержат в качестве дочерних узлов VehicleInfo DIV. Любые узлы DIV used_result_container, которые не содержат VehicleInfo, имеют дочерние элементы, не являются relavent.
Есть ли парсер регулярных выражений DOM с захватом и переадресацией? я не думаю, что XPath может выбирать узлы более высокого уровня на основе критериев узлов нижнего уровня:
\\div[@class="used_result_container" && .\div[@class="vehicleInfo"]]\*
Примечание. Я использую XPath так редко, что я не могу составить гипотетический синтаксис xpath очень хорошо.
Ответы
Ответ 1
Python:
lxml - быстрее, возможно, лучше разобрать плохой HTML
BeautifulSoup - если lxml не работает на вашем входе, попробуйте это.
Ruby: (слышал о следующих библиотеках, но никогда не пробовал их)
Nokogiri
hpricot
Хотя, если ваши парсеры задыхаются, и вы можете точно определить, что вызывает удушье, я, честно говоря, думаю, что можно использовать хакер regex, чтобы удалить эту часть, прежде чем передать ее парсеру.
Если вы решите использовать lxml, здесь some Учебники XPath, которые могут оказаться полезными. В учебниках lxml предполагается, что вы знаете, что такое XPath (чего я не делал, когда впервые их прочитал.)
Изменить: Ваше сообщение действительно выросло с тех пор, как оно впервые появилось... Я постараюсь ответить, что смогу.
Я не думаю, что XPath может выбирать узлы более высокого уровня на основе критериев узлов нижнего уровня:
Он может. Попробуйте //div[@class='vehicleInfo']/parent::div[@class='used_result_container']
. Используйте ancestor
, если вам нужно подняться на большее количество уровней. lxml также предоставляет метод getparent()
в результатах поиска, и вы тоже можете это использовать. Действительно, вы должны посмотреть на сайты XPath, которые я связал; вы, вероятно, можете решить свои проблемы оттуда.
как получить доступ к повторяющимся структурам данных?
Казалось бы, запросы DOM точно соответствуют вашим потребностям. Запросы XPath возвращают вам список найденных элементов - чего еще вы хотите? И, несмотря на его название, lxml действительно принимает "свободный HTML". Кроме того, анализатор распознает "знаковые записи" в HTML и соответствующим образом структурирует весь документ, поэтому вам не нужно делать это самостоятельно.
Да, вам все равно придется выполнять поиск по структуре, но на более высоком уровне абстракции. Если разработчики сайта решают сделать перестройку страницы и полностью изменить имена и структуру своих div
s, то это слишком плохо, вам нужно переписать свои запросы, но это займет меньше времени, чем переписывание вашего регулярного выражения. Ничто не сделает это автоматически для вас, если вы не хотите писать некоторые возможности AI в свой скребок страницы...
Я извиняюсь за то, что не предоставлял "собственные библиотеки Win32", сначала я предполагал, что вы просто подразумеваете "работает в Windows". Но другие ответили на эту часть.
Ответ 2
Используйте Html Agility Pack для .NET
Обновление
Так как вам нужно что-то родное/античное, а разметка, скорее всего, плохое, я бы рекомендовал запустить разметку через Tidy, а затем синтаксический анализ Xerces
Ответ 3
Native Win32
Вы всегда можете использовать IHtmlDocument2. В данный момент это встроено в Windows. С помощью этого COM-интерфейса вы получаете собственный доступ к мощному парсеру DOM (IE DOM parser!).
Ответ 4
Используйте Beautiful Soup.
Beautiful Soup - это синтаксический анализатор HTML/XML для Python, который может оказаться даже недействительным разметки в дерево разбора. Это обеспечивает простые, идиоматические способы навигации, поиск и изменение синтаксического анализа дерево. Это обычно спасает программистов часов или дней работы. Там также Рубиновый порт называется Rubyful Soup.
Ответ 5
Если вы действительно под Win32, вы можете использовать крошечный и быстрый COM-объект, чтобы сделать это
пример кода с vbs:
Set dom = CreateObject("htmlfile")
dom.write("<div>Click for <img src='http://www.google.com/images/srpr/logo1w.png'>Google</a></div>")
WScript.Echo(dom.Images.item(0).src)
Вы также можете сделать это в JScript, или VB/Dephi/С++/С#/Python и т.д. в Windows. Он использует макет mshtml.dll dom и парсер напрямую.
Ответ 6
Использовать парсер DOM
например. для java проверьте этот список
Open Source HTML Parsers в Java (мне нравится использовать cobra)
Или, если вы уверены, например. что вы только хотите проанализировать определенный подмножество вашего html, который в идеале также является xml, вы можете использовать некоторый синтаксический анализатор xml для анализа только того фрагмента, который вы передаете, а затем даже используйте xpath для запроса интересующих вас значений.
XML-парнеры с открытым исходным кодом в Java (например, dom4j прост в использовании)
Ответ 7
Альтернативой является использование анализатора html dom. К сожалению, похоже, что у большинства из них есть проблемы с плохо сформированным html, поэтому, кроме того, вам нужно запустить его через html-порядок или что-то подобное в первую очередь.
Ответ 8
Если парсер DOM не может быть и речи - по какой-то причине,
Я бы выбрал вариант PHP explode()
или все, что доступно на используемом вами языке программирования.
Вы можете, например, начать с разбиения на <div class="vehicleInfo">
, что даст вам каждый результат (помните, чтобы игнорировать первое место). После этого вы можете зацикливать результаты, разделяющие каждый результат на <div class="makemodeltrim">
и т.д.
Это отнюдь не оптимальное решение, и оно будет довольно хрупким (почти любое изменение в макете документа сломает код).
Другой вариант - перейти к некоторой библиотеке селекторов CSS, например phpQuery или аналогичной для вашего языка программирования.
Ответ 9
Я думаю, что libxml2, несмотря на свое имя, также делает все возможное, чтобы разобрать HTML-суп с тегами. Это C-библиотека, поэтому она должна удовлетворять вашим требованиям. Вы можете найти здесь.
BTW, еще один рекомендованный lxml ответ, который является библиотекой Python, но на самом деле построен на libxml2. Если lxml работал хорошо для него, скорее всего, libxml2 будет хорошо работать для вас.
Ответ 10
Как об использовании Internet Explorer в качестве элемента управления ActiveX? Это даст вам полностью визуализированную структуру, поскольку она просматривает страницу.
Ответ 11
Модули HTML:: Parser и HTML:: Tree в Perl довольно хорошо разбираются в наиболее типичном так называемом HTML в Интернете. Оттуда вы можете найти элементы, используя запросы, похожие на XPath.
Ответ 12
Что вы думаете о ihtmldocument2,
Я думаю, что это должно помочь.