2011-03-05 27 views
0

我需要解析python中的html文件,并将内容存储在列表中。 例子:['<html>', '<head>', '<meta name="robots" content="noindex">']如何读取文件的一部分(解析),中断python中的“<”字符?

这里是我现在对buggish功能:

def getTexte(fp,compte=0): #returns the text before a html tag 
    txt="" 
    pos=fp.tell() #stock the curr position for later use 
    tmppos=fp.tell() #same here 
    for car in fp.read(): 
     if car=="<": #if we encounter the start of a html tag 
      fp.seek(tmppos) #we get back to juste before the html tag 
      break # and we leave this damn for 
     txt=txt+car #we concatenate each car in the string 
     tmppos=fp.tell() #and stock the pos for later use 
    if compte==0: 
     fp.seek(pos) 
    if txt!="": 
     return txt 

现在,这里是一个示例输出,我得到:

['<p>', 'Blablabla', 'lablabla', 'ablabla', 'blabla', 'labla', 'abla', 'bla', 'la', 'a', '</p>'] 

,我无法理解为什么。也许太累了。

+1

为什么不使用像BeautifulSoup这样的解析器? – 2011-03-05 08:56:36

+2

(1)HTML解析是一个解决的问题,甚至处理无效的,完全虚假的“标记”。 (2)你现在只是标记。解析还有很多。 (3)用手写一个词法分析器(没有正则表达式,见4)很难。手工编写完整的解析器对于大多数解析任务来说都是不切实际的。 (4)如果你打算用手工做,最好的选择是FSM,即一个正则表达式(手工编写非平凡的FSM又是非常丑陋和不需要的)。 – delnan 2011-03-05 09:00:48

+0

也许你可以添加到你的问题最有帮助的事情是解释你真的想要解决什么问题。 (例如,不清楚为什么要将这些元素放在展开的列表中,或者想要在元素中包含文本时想要发生什么等) – 2011-03-05 09:22:27

回答

4

正如其他人在他们的评论中所说的,你真的不想试图通过迭代输入作为一系列字符来编写HTML解析器。您的代码片段对tell()和方法的引用表明您正在考虑通过打开文件而不是考虑更高级别(将文档作为字符串读入缓冲区)。

有许多工具已经编写,可以免费使用,经过广泛测试,维护良好并广受好评,专门为您执行此类任务而设计。迄今为止,这些中最受欢迎的是名为“BeautifulSoup”的软件,该软件以其“在真实世界中”发现的那种HTML的稳健性和宽容而闻名。大致来说,BeautifulSoup的目标是解析浏览器可以合理显示的任何HTML。因此,它可以处理HTML中的各种极其常见的错误 - 不正确嵌套的标签,缺少结束标签的容器,非标准“标签”以及非标准和不合格属性和属性=值对等标签。

下面是使用BeautifulSoup一些Python代码进行非常简单的例子:

#!/bin/env python 

import urllib2 
from BeautifulSoup import BeautifulSoup 

def get_page(url): 
    fetcher = urllib2.urlopen(url) 
    results = fetcher.read() 
    fetcher.close() 
    return results 

def find_tags(data): 
    results = list() 
    parser = BeautifulSoup(data) 
    results.extend(parser.findAll()) 
    return results 

if __name__ == '__main__': 
    import sys, time 

    for url in sys.argv[1:]: 
     html=get_page(url) 
     for n, each in enumerate([str(x) for x in find_tags(html)]): 
      print n, each, '\n\n\n' 

...你可以看到BeautifulSoup引用只占少数这里的线。剩下的就是获取HTML并打印结果。

顺便说一句,这些结果并不完全符合您的要求,因为它们表示从最外层向下到每个HTML容器的深度遍历,以及从这些元素到它的组件,等等。在你的代码中,你可能想要遍历这棵树,并确定你在叶子上的时间,然后以某种方式捕获文本/内容或标签/代码。您需要阅读BeautifulSoup: Documentation以了解更加精确地匹配您的需求的详细信息。

+0

为什么不使用''results = fetcher.read()' ** ** find_page(url)**和''results = parser.findAll()''in ** find_tags(data)**? – eyquem 2011-03-05 16:51:04

+0

@eyquem:这段代码实际上是从我工作时运行的一个小内部工具中粘贴的。 (它从内部监控应用程序中刮取仪表板页面,不会公开任何其他方便的界面供我查询)。这里的代码被刻意简化为接近最小...但稍微冗长易于阅读,因为我的代码有一些异常处理和其中讨厌的细节。 .readlines()优先于.read()在内容中啜泣是个人的怪癖。这是我习惯的(但改变它)。我使用.extend()强制结果到列表中,而不是BS obj – 2011-03-06 01:54:14

0

如果您只需要使用解析html的输出,那么看看Beautiful Soup。已经做了大量的工作,确保HTML(和XML)被正确解析,即使您提供非有效标记。

您是否需要构建解析器?或者你只是需要使用解析器的输出?这将决定你从StackOverflow获得的帮助。很多时候,通过将您的意图(需求)与您提出的解决方案和问题一起知道,人们会指出可能更适合您需求的替代解决方案。食物的思想。

相关问题