使用python提取html文件中的特定数据的实现代码_python

例如 具有如下结构的html文件

复制代码 代码如下:

<div class='entry-content'>
<p>感兴趣内容1</p>
<p>感兴趣内容2</p>
……
<p>感兴趣内容n</p>
</div>
<div class='content'>
<p>内容1</p>
<p>内容2</p>
……
<p>内容n</p>
</div>

我们尝试获得'感兴趣内容'

对于文本内容,我们保存到IDList中。
可是如何标记我们遇到的文本是感兴趣的内容呢,也就是,处于

复制代码 代码如下:

<div class='entry-content'>
<p>这里的内容</p>
<p>还有这里</p>
……
<p>以及这里的内容</p>
</div>

思路如下

  1. 遇到<div class='entry-content'> 设置标记flag = True
  2. 遇到</div>后 设置标记flag = False
  3. 当flag 为True时遇到<p> 设置标记getdata = True
  4. 遇到</p> 且getdata = True,设置getdata = False

python为我们提供了SGMLParser类,SGMLParser 将 HTML 分析成 8 类数据[1],然后对每一类调用单独的方法:使用时只需继承SGMLParser 类,并编写页面信息的处理函数。

可用的处理函数如下

  • 开始标记 (Start tag) 

是一个开始一个块的 HTML 标记,象 <html>,<head>,<body> 或 <pre> 等,或是一个独一的标记,象 <br> 或 <img> 等。当它找到一个开始标记 tagname,SGMLParser 将查找名为 start_tagname 或 do_tagname 的方法。例如,当它找到一个 <pre> 标记,它将查找一个 start_pre 或 do_pre 的方法。如果找到了,SGMLParser 会使用这个标记的属性列表来调用这个方法;否则,它用这个标记的名字和属性列表来调用 unknown_starttag 方法。 

  • 结束标记 (End tag) 

是结束一个块的 HTML 标记,象 </html>,</head>,</body> 或 </pre> 等。当找到一个结束标记时,SGMLParser 将查找名为 end_tagname 的方法。如果找到,SGMLParser 调用这个方法,否则它使用标记的名字来调用 unknown_endtag 。 

  • 字符引用 (Character reference) 

用字符的十进制或等同的十六进制来表示的转义字符,象  。当找到,SGMLParser 使用十进制或等同的十六进制字符文本来调用 handle_charref 。 

  • 实体引用 (Entity reference) 

HTML 实体,象 。当找到,SGMLParser 使用 HTML 实体的名字来调用 handle_entityref 。 

  • 注释 (Comment) 

HTML 注释, 包括在 <!-- ... -->之间。当找到,SGMLParser 用注释内容来调用 handle_comment。 

  • 处理指令 (Processing instruction) 

HTML 处理指令,包括在 <? ... > 之间。当找到,SGMLParser 用处理指令内容来调用 handle_pi。 

  • 声明 (Declaration) 

HTML 声明,如 DOCTYPE,包括在 <! ... >之间。当找到,SGMLParser 用声明内容来调用 handle_decl。 

  • 文本数据 (Text data) 

文本块。不满足其它 7 种类别的任何东西。当找到,SGMLParser 用文本来调用 handle_data。 

综上,的到如下代码

复制代码 代码如下:

from sgmllib import SGMLParser
class GetIdList(SGMLParser):
    def reset(self):
        self.IDlist = []
        self.flag = False
        self.getdata = False
        SGMLParser.reset(self)

    def start_div(self, attrs):
        for k,v in attrs:#遍历div的所有属性以及其值
            if k == 'class' and v == 'entry-content':#确定进入了<div class='entry-content'>
                self.flag = True
                return

    def end_div(self):#遇到</div>
 self.flag = False

    def start_p(self, attrs):
        if self.flag == False:
            return
        self.getdata = True

复制代码 代码如下:

    def end_p(self):#遇到</p>
        if self.getdata:
            self.getdata = False

    def handle_data(self, text):#处理文本
        if self.getdata:
            self.IDlist.append(text)

复制代码 代码如下:

    def printID(self):
        for i in self.IDlist:
            print i

上面的思路存在一个bug
遇到</div>后 设置标记flag = False
如果遇到div嵌套怎么办?

复制代码 代码如下:

<div class='entry-content'><div>我是来捣乱的</div><p>感兴趣</p></div>

在遇到第一个</div>之后标记flag = False,导致无法的到‘感兴趣内容'。
怎么办呢?如何判断遇到的</div>是和<div class='entry-content'>匹配的哪个呢?
很简单,</div>和<div>是对应的,我们可以记录他所处的层数。进入子层div verbatim加1,退出子层div  verbatim减1.这样就可以判断是否是同一层了。

修改后 如下

复制代码 代码如下:

from sgmllib import SGMLParser
class GetIdList(SGMLParser):
    def reset(self):
        self.IDlist = []
        self.flag = False
        self.getdata = False
        self.verbatim = 0
        SGMLParser.reset(self)

    def start_div(self, attrs):
        if self.flag == True:
            self.verbatim +=1 #进入子层div了,层数加1
            return
        for k,v in attrs:#遍历div的所有属性以及其值
            if k == 'class' and v == 'entry-content':#确定进入了<div class='entry-content'>
                self.flag = True
                return

    def end_div(self):#遇到</div>
        if self.verbatim == 0:
            self.flag = False
        if self.flag == True:#退出子层div了,层数减1
            self.verbatim -=1

    def start_p(self, attrs):
        if self.flag == False:
            return
        self.getdata = True

    def end_p(self):#遇到</p>
        if self.getdata:
            self.getdata = False

    def handle_data(self, text):#处理文本
        if self.getdata:
            self.IDlist.append(text)

    def printID(self):
        for i in self.IDlist:
            print i

最后  建立了我们自己的类GetIdList后如何使用呢?
简单建立实例 t = GetIdList()
the_page为字符串,内容为html
t.feed(the_page)#对html解析

t.printID()打印出结果

全部测试代码为

复制代码 代码如下:

from sgmllib import SGMLParser
class GetIdList(SGMLParser):
    def reset(self):
        self.IDlist = []
        self.flag = False
        self.getdata = False
        self.verbatim = 0
        SGMLParser.reset(self)

    def start_div(self, attrs):
        if self.flag == True:
            self.verbatim +=1 #进入子层div了,层数加1
            return
        for k,v in attrs:#遍历div的所有属性以及其值
            if k == 'class' and v == 'entry-content':#确定进入了<div class='entry-content'>
                self.flag = True
                return

    def end_div(self):#遇到</div>
        if self.verbatim == 0:
            self.flag = False
        if self.flag == True:#退出子层div了,层数减1
            self.verbatim -=1

    def start_p(self, attrs):
        if self.flag == False:
            return
        self.getdata = True

    def end_p(self):#遇到</p>
        if self.getdata:
            self.getdata = False

    def handle_data(self, text):#处理文本
        if self.getdata:
            self.IDlist.append(text)

    def printID(self):
        for i in self.IDlist:
            print i

##import urllib2
##import datetime
##vrg = (datetime.date(2012,2,19) - datetime.date.today()).days
##strUrl = 'http://www.nod32id.org/nod32id/%d.html'%(200+vrg)
##req = urllib2.Request(strUrl)#通过网络获取网页
##response = urllib2.urlopen(req)
##the_page = response.read()

the_page ='''<html>
<head>
<title>test</title>
</head>
<body>
<h1>title</h1>
<div class='entry-content'>
<div class= 'ooxx'>我是来捣乱的</div>
<p>感兴趣内容1</p>
<p>感兴趣内容2</p>
……
<p>感兴趣内容n</p>
<div class= 'ooxx'>我是来捣乱的2<div class= 'ooxx'>我是来捣乱的3</div></div>
</div>
<div class='content'>
<p>内容1</p>
<p>内容2</p>
……
<p>内容n</p>
</div>
</body>
</html>
'''
lister = GetIdList()
lister.feed(the_page)
lister.printID()

执行后 输出为

复制代码 代码如下:

感兴趣内容1
感兴趣内容2
感兴趣内容n

参考文献

[1] 深入 Python:Dive Into Python 中文版

时间: 2024-08-02 10:12:35

使用python提取html文件中的特定数据的实现代码_python的相关文章

matlab中如何提取数据文件中的特定行和列?

问题描述 matlab中如何提取数据文件中的特定行和列? 一个数据文件,我想提取它的第一到第四列,以及第九列 和第1到500行,以及501到1000行? 解决方案 data = []; data = original(:,1:4);其他类似

python读取txt文件中的array

问题描述 python读取txt文件中的array 一个txt文件中的文本格式如下所示: [[-0.056557,0.053254],[-0.042491,0.040662],[-0.061258,0.067239],[-0.067659,0.044261]] 怎样从这个txt中将它都成np.array的格式 解决方案 本文直接给出三种实现方法,代码如下. 方法一: f = open("Proc_Data.txt") # 返回一个文件对象 line = f.readline() # 调

我想知道怎样提取pdf文件中的图片,因为我想把pdf文件转换为doc,还有别的形式,可是利用pdfbox只能提取出文本来,希望大家提供点办法,急呀

问题描述 我想知道怎样提取pdf文件中的图片,因为我想把pdf文件转换为doc,还有别的形式,可是利用pdfbox只能提取出文本来,希望大家提供点办法,急 解决方案 解决方案二:你从网上下载个PDF转化DOC工具就得了啊,很多的,到处都是咧解决方案三:貌似使用adobe的打印到文件就可以转换成doc文件解决方案四:你从网上下载个PDF转化DOC工具

在Python的Flask框架中使用日期和时间的教程_python

 时间戳的问题 我们的微博应用的一个忽略了很久的问题就是日间和日期的显示. 直到现在,我们在我们的User和Post对象中使用Python它自己的方式来渲染时间对象,但这并不是一个好的解决方案. 考虑下这样的例子.我正在写这篇文章,此时正是12月31号下午3:54.我的时区是PST(或者你们更习惯的:UTC-8). 在Python解释器中运行,我得到下面输出:   >>> from datetime import datetime >>> now = datetime.

在遍历文件中写了显示图片的代码,通过控件做显示循环除了问题,麻烦了

问题描述 在遍历文件中写了显示图片的代码,通过控件做显示循环除了问题,麻烦了 我想循环显示图像,在遍历文件中写了显示图片的代码,通过控件做显示循环,调试没问题,运行的时候出现ASSERT(m_hFile != INVALID_HANDLE_VALUE)这一句,设置断点之后发现if(!file.open)这句有问题,有高手能为我解答一下吗,弄了好久没弄出来,麻烦了 void CbianliDoc::OnOpenfile() { // 判断当前图像是否已经被改动 if (IsModified())

c++ 编程问题-.txt文件中删除某些数据而保留其他数据

问题描述 .txt文件中删除某些数据而保留其他数据 比如我有个.txt文件,名字叫aaa 里面有数据是这样的: 第一行11111 第二行23222 第三行32562 那么怎么才能用C++的代码实现把第二行删除掉,而保留第一行和第三行呢? 求代码,最后带一些解析 解决方案 先用ostream对象把文件读到一个缓冲区,然后对缓冲区修改,最后将缓冲区用istream对象写入到文件就行了,主要是对缓冲区的操作而已

《R数据可视化手册》——1.5 从SPSS文件中加载数据

1.5 从SPSS文件中加载数据 问题如何从SPSS文件加载数据? 方法foreign包中的函数read.spss()可以读取SPSS文件.若要读取SPSS文件中的第一张表: #只需首次使用时安装 install.packages("foreign") library(foreign) data <-read.spss("datafile.sav") 讨论foreign包中还有很多读取其他格式文件的函数,包括以下几种. read.octave():Octave

《R数据可视化手册》一1.5 从SPSS文件中加载数据

1.5 从SPSS文件中加载数据 问题如何从SPSS文件加载数据? 方法foreign包中的函数read.spss()可以读取SPSS文件.若要读取SPSS文件中的第一张表: #只需首次使用时安装 install.packages("foreign") library(foreign) data <-read.spss("datafile.sav") 讨论foreign包中还有很多读取其他格式文件的函数,包括以下几种. read.octave():Octave

《R数据可视化手册》一1.4 从Excel文件中加载数据

1.4 从Excel文件中加载数据 问题如何从Excel文件中加载数据? 方法xlsx包中的函数read.xlsx()可以读取Excel文件,下面的代码将会读取Excel中的第一个工作表: #只需要安装一次 install.packages("xlsx") library(xslx) data <-read.xlsx("datafile.xlsx", 1) 如果需要阅读老版本的Excel文件(.xls格式),gdata包提供了函数read.xls(): # 只