HTMLParser提取网页

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTMLParser提取网页相关的知识,希望对你有一定的参考价值。

假设有如下一段代码:
<div class="article">
这是无用内容
<b>这是无用内容</b>
这是有效文本
<img src=“a.jpg”/>
这是有效文本
<img src=“b.jpg”/>
这是有效文本
<img src=“c.jpg”/>
</div>
想用htmlParser把所有有效文本都提取出来,不想一个一个慢慢提取,因为文本和IMG标签重复次数不确定。有智能一点的办法吗?多谢~~

HTMLParser只是一个HTML解析器,现在还有一个更高级的叫做:Java Mozilla HTML parser,是国外的Dapper公司将Mozilla的浏览器解析器用Java编程语言进行了封装,用于他们的著名的语义网络服务网站,后来开源出来贡献给社区。

用解析器将HTML解析成DOM后,应该使用一种合理的方法从DOM中将内容提取出来,例如,XPath和XSLT,上述需求就可以用XSLT提取,XSLT根据匹配规则找出来的是一个节点集合,所以能够解决你说的重复次数不确定的问题,但是,XSLT提取规则并不好编写,可以采用免费软件MetaSeeker,能够自动生成XSLT规则,也可以局部定制规则片段。

欢迎访问我的博客或者访问GooSeeker网站,上面有很多技术资料。
参考技术A 找找规律性

如何使用 python HTMLParser 库从特定的 div 标签中提取数据?

【中文标题】如何使用 python HTMLParser 库从特定的 div 标签中提取数据?【英文标题】:How can I use the python HTMLParser library to extract data from a specific div tag? 【发布时间】:2011-03-17 14:30:12 【问题描述】:

我正在尝试使用 python HTMLParser 库从 HTML 页面中获取值。我想要获取的值在这个 html 元素中:

...
<div id="remository">20</div>
...

到目前为止,这是我的 HTMLParser 类:

class LinksParser(HTMLParser.HTMLParser):
  def __init__(self):
    HTMLParser.HTMLParser.__init__(self)
    self.seen = 

  def handle_starttag(self, tag, attributes):
    if tag != 'div': return
    for name, value in attributes:
    if name == 'id' and value == 'remository':
      #print value
      return

  def handle_data(self, data):
    print data


p = LinksParser()
f = urllib.urlopen("http://domain.com/somepage.html")
html = f.read()
p.feed(html)
p.close()

有人能指出我正确的方向吗?我希望类功能获得值 20。

【问题讨论】:

如果你在做大量的 HTML 解析,试试Beautiful Soup。 该库是否作为 python 标准库包含在内?我遇到过它,但选择坚持使用 HTMLParser。 @zvone 为什么 BeautifulSoup 更适合 html 解析?它仍然是推荐的模块吗?谢谢。 @tommy.carstensen BeautifulSoup4 通常被推荐用于网页抓取和解析特定标签的 HTML。它具有定位特定标签的方法,使用 lxml 和 html5lib 库,并为您处理将传入文档转换为 Unicode 并将传出文档转换为 UTF-8。简而言之,它可以在短短几行代码中完成您对丑陋的 HTML 页面所做的一切。查看the bs4 docs! :) @tommy.carstensen 我已经多年没有使用 BeautifulSoup(或解析过的 HTML)了。现在可能有更好的东西。无论如何,它的好处是它在结构糟糕的 HTML 上表现得更好。无效的 HTML 比有效的 HTML 更容易被看到,因此表现良好总是一个加分项。 【参考方案1】:

这很好用:

print (soup.find('the tag').text)

【讨论】:

【参考方案2】:

你试过BeautifulSoup 吗?

from bs4 import BeautifulSoup
soup = BeautifulSoup('<div id="remository">20</div>')
tag=soup.div
print(tag.string)

这会在输出时为您提供20

【讨论】:

【参考方案3】:

第 3 行的小修正

HTMLParser.HTMLParser.__init__(self)

应该是

HTMLParser.__init__(self)

以下内容对我有用

import urllib2 

from HTMLParser import HTMLParser  

class MyHTMLParser(HTMLParser):

  def __init__(self):
    HTMLParser.__init__(self)
    self.recording = 0 
    self.data = []
  def handle_starttag(self, tag, attrs):
    if tag == 'required_tag':
      for name, value in attrs:
        if name == 'somename' and value == 'somevale':
          print name, value
          print "Encountered the beginning of a %s tag" % tag 
          self.recording = 1 


  def handle_endtag(self, tag):
    if tag == 'required_tag':
      self.recording -=1 
      print "Encountered the end of a %s tag" % tag 

  def handle_data(self, data):
    if self.recording:
      self.data.append(data)

 p = MyHTMLParser()
 f = urllib2.urlopen('http://www.someurl.com')
 html = f.read()
 p.feed(html)
 print p.data
 p.close()

`

【讨论】:

实际上你可以这样做,因为你指定了from HTMLParser import HTMLParser,它允许你直接调用HTMLParser。不幸的是,它们都具有相同的名称,但它们是两个不同的实体。您也可以执行from HTMLParser import HTMLParser as parser 之类的操作,然后使用class MyHTMLParser(parser)【参考方案4】:
class LinksParser(HTMLParser.HTMLParser):
  def __init__(self):
    HTMLParser.HTMLParser.__init__(self)
    self.recording = 0
    self.data = []

  def handle_starttag(self, tag, attributes):
    if tag != 'div':
      return
    if self.recording:
      self.recording += 1
      return
    for name, value in attributes:
      if name == 'id' and value == 'remository':
        break
    else:
      return
    self.recording = 1

  def handle_endtag(self, tag):
    if tag == 'div' and self.recording:
      self.recording -= 1

  def handle_data(self, data):
    if self.recording:
      self.data.append(data)

self.recording 从“触发”标签开始计算嵌套的 div 标签的数量。当我们在以触发标签为根的子树中时,我们将数据累积在self.data中。

解析结束时的数据留在self.data 中(字符串列表,如果没有遇到触发标记,可能为空)。您来自类外部的代码可以在解析结束时直接从实例访问列表,或者您可以为此目的添加适当的访问器方法,具体取决于您的目标。

通过使用'div''id''remository',实例属性self.tag、@987654330 来代替上面代码中看到的常量文字字符串,可以轻松地使该类更通用@ 和 self.attvalue,由 __init__ 从传递给它的参数中设置——我避免在上面的代码中进行廉价的泛化步骤以避免混淆核心点(跟踪嵌套标签的计数并将数据累积到列表中)录制状态为激活状态)。

【讨论】:

感谢 Alex,该代码运行良好(除了这一行“if tag == div and self.recording:” - div 应该是一个字符串)。我所说的类返回值的意思实际上正如您所描述的那样,是类中返回所需值的函数。或者我可以轻松访问“数据”变量。我在那里的字典只是我测试可能的解决方案的一些残余:) 感谢您的帮助! +1 表示嵌套 divs 的计数,这对于第一次进行 html 解析的人来说并不那么明显。 @Martin,不客气,+1 以发现我的分心——我现在将进行编辑以修复(引用 div 并删除该字典和评论),以便对未来的读者更有用. 如果数据是 unicode 怎么办,例如数据是日文或中文,如何将其附加到 data[] 列表中?

以上是关于HTMLParser提取网页的主要内容,如果未能解决你的问题,请参考以下文章

求帮忙制作一个JAVA HTMLParser Extractor解析器类 从HTML中提取所需要的信息

python中HTMLParser简单理解

Python中的HTMLParsercookielib抓取和解析网页从HTML文档中提取链接图像文本Cookies

python HTMLParser

htmlparser API

使用 Python 模块—— HTMLParser 解析 HTML 文档元素