设为首页 收藏本站
查看: 1131|回复: 0

[经验分享] Python:HTMLParser模块进行简单的html解析

[复制链接]

尚未签到

发表于 2018-8-11 11:42:03 | 显示全部楼层 |阅读模式
  这是从用Python开发开始到现在第二次使用HTMLParser模块进行html解析了,第一次用的时候,由于是刚刚接触Python,对其中的一些用法不是很理解,因为赶进度,虽然照着参考资料也写出来了,但是其中的原理还是不怎么了解。第二次用的时候,有一定的经验了,对Python的理解也更加深刻了,所以第二次用的时候,对HTMLParser模块的一些用法不像第一次用时那么茫然。结合鄙人第二次用该模块的经验,来讲讲HTMLParser模块的基本使用方法,希望对你有帮助。
  HTMLParser是python用来解析html的模块。它可以分析出html里面的标签、数据等等,是一种处理html的简便途径。HTMLParser采用的是一种事件驱动的模式,当HTMLParser找到一个特定的标记时,它会去调用一个用户定义的函数,以此来通知程序处理。它主要的用户回调函数的命名都是以handler_开头的,都是HTMLParser的成员函数。当我们使用时,就从HTMLParser派生出新的类,然后重新定义这几个以handler_开头的函数即可。这几个函数包括:
  handle_startendtag(tag, attrs)  处理开始标签和结束标签
  handle_starttag(tag, attrs)     处理开始标签,比如<xx>
  handle_endtag(tag)       处理结束标签,比如</xx>
  handle_charref(name)      处理特殊字符串,就是以&#开头的,一般是内码表示的字符
  handle_entityref(name)    处理一些特殊字符,以&开头的,比如 &nbsp;
  handle_data(data)         处理数据,就是<xx>data</xx>中间的那些数据
  handle_comment(data)      处理注释
  handle_decl(decl)         处理<!开头的,比如<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  handle_pi(data)           处理形如<?instruction>的东西
  tag是的html标签,attrs是 (属性,值)元组(tuple)的列表(list).
  HTMLParser自动将tag和attrs都转为小写。
  下面以从中国银行官网上解析html文件以获取实时汇率(这就是我第二此用该模块时的解析任务)为例,来定义一个HTMLParser派生类。
  在构造这个派生类之前,肯定要分析网页的源码的,找出你要获取的那一个值,在此不做介绍。直接上代码了,要仔细理解
#coding=utf-8  
import HTMLParser
  
import requests
  
class MyHTMLParser(HTMLParser.HTMLParser):
  
    """
  

  
    """
  
    def __init__(self):
  
        HTMLParser.HTMLParser.__init__(self)
  
        self.result = []#记录结果
  
        self.flag = False#标记
  

  

  
    def handle_starttag(self,tag,attrs):
  
        if tag == "td" and self.flag == False and len(attrs) == 0:
  
        #attrs(属性,值)元组(tuple)的列表(list),由于我要获取的值的html标签的没有属性
  
        #所以要求它长度0以排除其它有属性的标签,缩小获取结果的范围。
  
        #如果有属性的话,attrs不会为空,它是元组列表可以用条件语句来判断
  
            self.flag = True
  

  
    def handle_end(self,tag):
  
        if tag == "td" and self.flag == True:
  
            self.flag = False
  

  
    def handle_data(self, data):
  
        if self.flag == True:
  
            self.result.append(data)
  上面代码不难理解,都是重载HTMLParser类里的方法。
  再接着就是爬取网页了,获取数据,代码如下:
def _filter_string(string):  
    """
  
    除去字符串中的空格,换行等等
  
    由于网页源码中空格、换行符等会使返回的结果中带有换行符(\t)等,所以在此除去,
  
    其实也可以得到结果(返回的结果是个列表)后用列表的内建方法除去这些带有换行符的元素,
  
    其实这样用‘+’拼接字符串的效率很低,这个问题我也是刚刚发现,过段时间在研究一下,
  
    找到了好的方法,再跟大家分享下。
  
    """
  
    s = ''
  
    for one in string:
  
        if one != '\n' and one != '\r' and one != '\t' and one != ' ':
  
            s = s + one
  
    return s
  

  
def get_rate():
  
    """
  
    获取汇率
  
    Returns:
  

  
    """
  
    url = "http://srh.bankofchina.com/search/whpj/search.jsp"
  
    headers = {'user-agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0'}
  
    usd_data = {
  
                 'pjname':1316,#美元在中国银行官网的代码
  
                }
  
    hkd_data = {
  
                 'pjname':1315,#港币在中国银行官网的代码
  
                 }
  
    usd_result = requests.post(url, data=usd_data, headers=headers)
  
    hkd_result = requests.post(url, data=hkd_data, headers=headers)
  
    usd_parser = MyHTMLParser()
  
    hkd_parser = MyHTMLParser()
  
    usd_text = usd_result.text
  
    hkd_text = hkd_result.text
  
    # text = _filter_string(text)
  
    usd_text = _filter_string(usd_text)
  
    hkd_text = _filter_string(hkd_text)
  

  
    usd_parser.feed(usd_text)
  
    usd_parser.close()
  
    # print usd_result.text
  
    hkd_parser.feed(hkd_text)
  
    hkd_parser.close()
  
    usd_start = usd_parser.result.index(u"美元")  # 美元第一个出现的位置是最新值
  
    usd_rate = usd_parser.result[usd_start + 3]
  
    usd_rate = float(usd_rate) / 100  # 最新美元汇率
  
    usd_uptime = usd_parser.result[usd_start + 7]  # 发布时间
  
    hkd_start = hkd_parser.result.index(u"港币")
  
    hkd_rate = hkd_parser.result[hkd_start + 3]
  
    hkd_rate = float(hkd_rate) / 100
  
    hkd_uptime = hkd_parser.result[hkd_start + 7]  # 发布时间
  
    return usd_rate, usd_uptime, hkd_rate, hkd_uptime
  HTMLParser类的其它一些方法:
  HTMLParser.reset()
  重置该实例。失去所有未处理的数据。这个在实例化对象时被隐含地调用。
  HTMLParser.feed(data)
  提供一些文本给解析器。在由完整元素组成的限度内进行处理,不完整的数据被缓冲直到更多的数据提供或者close()被调用。
  HTMLParser.close()
  强制将所有的缓冲数据按跟在结束标记的数据一样进行处理。该方法可以通过派生类定义对输入结尾的额外处理来进行重定义,但是重定义的版本应该总是调用HTMLParser基类方法close()
  HTMLParser.getpos()
  返回当前行数和位移值。
  HTMLParser.get_starttag_text()
  返回当前位置最近的开始标签的内容
  这是给公司内部财务人员记账用的,所以做成了API供调用。隐约感觉上面代码最后几行获取结果的方法不是最佳方法,如果你有更好的方法,欢迎您与我分享,如果我找到了更好的我会及时分享给大家。
  当然,如果是个简单的任务,用HTMLParser模块抓取一些想要的数据还是绰绰有余,如果是复杂的任务,有一定要求(比如性能要求)的任务,那就要用第三方库,比如Beautiful Soup,不过这个库我没用过,有时间研究一下,然后再和大家分享一下我的学习习得。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-550102-1-1.html 上篇帖子: python小游戏之圣诞树 下篇帖子: python面试题之--打乱排好序的list
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表