Win32 .:如何在没有正则表达式的情况下擦除HTML?

最近的一个 blog entry by a Jeff Atwood说,你绝对不应该使用正则表达式来解析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

你可以看到我想要提取的值,[括在括号中]:

>网址
> MakeAndModel
>公里
>价格
>位置

假设我们接受解析HTML的前提:

一般都是坏主意
> rapidly devolves into madness

做什么的方法?

假设:

>本机Win32
>松散的html

假设澄清:

本地Win32

> .NET / CLR不是本机的Win32
> Java不是本机的Win32
> perl,python,ruby不是本机的Win32
>假设C在Visual Studio 2000中编译成本机的Win32应用程序

本地Win32应用程序可以调用库代码:

>复制源代码
>包含功能入口点的DLL
>包含COM对象的DLL
>包含COM对象的DLL,这些对象是托管.NET对象周围的COM可调用的包装器(CCW)

宽松的HTML

> xml不是松散的HTML
> xhtml不是松散的HTML
>严格HTML不宽松的HTML

宽松的HTML意味着HTML不是格式正确的xml(严格的HTML格式不太完整),所以XML解析器不能使用.实际上,我认为任何HTML解析器必须在它接受的HTML中是大方的假设.

澄清#2

假设您喜欢将HTML转换为文档对象模型(DOM),那么您如何访问重复的数据结构?你将如何走DOM树?我需要一个DIV节点,它是一类used_result_container,它具有一个类的车辆信息的子DIV.但节点不一定是彼此的直接子节点.

听起来我正在为另一个交易一套正则表达式问题.如果他们改变HTML的结构,我将不得不重写我的代码来匹配 – 就像我将用正则表达式.假设我们想避免这些问题,因为那些是正则表达式的问题,我该怎么办?

我会不会为DOM节点编写正则表达式解析器?我正在编写一个引擎来解析一串对象,使用内部状态机和前进和后退捕获.不,必须有一个更好的方式 – 杰夫提到的方式.

我故意保持原来的问题模糊,以免引导人们走错路.我不想暗示解决方案必然与之有关:

>走DOM树
> xpath查询

澄清#3

我提供的示例HTML修剪了重要的元素和属性.我用来修剪HTML的机制是基于我使用正则表达式的内部偏差.我自然认为我需要在我寻找的HTML中的各种“签名.

所以不要混淆整个HTML中呈现的HTML.也许一些其他解决方案取决于所有原始HTML的存在.

更新4

唯一支持的解决方案似乎涉及使用库将HTML转换为文档对象模型(DOM).那么问题就是要成为:那么什么呢?

现在我有DOM,我该怎么办?似乎我仍然必须用某种常规的DOM表达式解析器来走树,能够进行前向匹配和捕获.

在这种特殊情况下,我需要所有包含vehicleInfo DIV节点的used_result_container DIV节点作为子节点.任何不包含车辆信息的used_result_container DIV节点都有一个小孩不相关.

是否有一个具有捕获和转发匹配的DOM正则表达式解析器?我不认为XPath可以根据较低级节点的标准选择更高级的节点:

\\div[@class="used_result_container" && .\div[@class="vehicleInfo"]]\*

注意:我很少使用XPath,我不能很好地弥补假设的xpath语法.

蟒蛇:

lxml – 更快,也许更好地解析不良的HTML

BeautifulSoup – 如果您输入的lxml失败,请尝试此操作.

Ruby:(听说过以下图书馆,但从未尝试过)

Nokogiri

hpricot

尽管如果您的解析器阻塞,您可以粗略地确定导致窒息的原因,我坦白地认为,在将其传递给解析器之前,请使用正则表达式hack删除该部分.

如果你决定使用lxml,那么here是可以找到的some XPath教程. lxml教程就是假设你知道XPath是什么(当我第一次阅读它的时候我没有看到)

编辑:自从第一次出现以来,你的帖子已经有所增长了,我会尽力回答我能做的事情.

i don’t think XPath can select higher level nodes based on criteria of lower level nodes:

它可以.尝试// div [@ class =’vehicleInfo’] / parent :: div [@ class =’used_result_container’].使用祖先,如果你需要上升更多的水平. lxml还在其搜索结果中提供了一个getparent()方法,您也可以使用它.真的,你应该看看我链接的XPath网站;你可以从那里解决你的问题.

how then do you access repeating structures of data?

看来,DOM查询完全符合您的需求. XPath查询返回您找到的元素的列表 – 您还想要什么?尽管它的名称,lxml确实接受“松散的HTML”.此外,解析器识别HTML中的“签名”,并相应地构建整个文档,因此您不必自己动手.

是的,你仍然需要对结构进行搜索,但是在更高的抽象层次上.如果站点设计者决定进行页面修改,并彻底改变其div的名称和结构,那么这太糟糕了,你必须重写你的查询,但是比重写正则表达式要花费更少的时间.没有什么会自动为您做,除非你想写一些AI功能到您的页面刮刀…

对于不提供’本地Win32’库的我深表歉意,我首先假设您只是想在Windows上运行.但其他人回答了这一点.

相关文章

文章浏览阅读2.2k次,点赞6次,收藏20次。在我们平时办公工作...
文章浏览阅读1k次。解决 Windows make command not found 和...
文章浏览阅读3.2k次,点赞2次,收藏6次。2、鼠标依次点击“计...
文章浏览阅读1.3w次。蓝光版属于高清版的一种。BD英文全名是...
文章浏览阅读974次,点赞7次,收藏8次。提供了更强大的功能,...
文章浏览阅读1.4w次,点赞5次,收藏22次。如果使用iterator的...