【Python入门】常用自带模块之HTMLParser

学习python的第7天

Python的自带模块——HTMLParser的初步学习
 

HTMLParser是Python自带的模块,使用简单,能够很容易的实现HTML文件的分析。
本文主要简单讲一下HTMLParser的用法。

使用时需要定义一个从模块html.parser中的类HTMLParser继承的类,重定义函数:

handle_starttag( tag, attrs)
handle_startendtag( tag, attrs)
handle_endtag( tag)
handle_data(data)

1.获取标签属性

tag是html的标签,attrs是(属性,值)tuple组成的list

如一个标签为:

<input type="hidden" name="NXX" id="IDXX" value="VXX" />

那么其attrs列表为:

[(‘type’, ‘hidden’), (‘name’, ‘NXX’), (‘id’, ‘IDXX’), (‘value’, ‘VXX’)]
  • HTMLParser自动将tagattrs都转为小写。

2.获取标签内容

解析时碰到<***>,自动调用handle_starttag();碰到</***>,自动调用handle_endtag()
每一个标签,无论<> 还是</>,均会调用handle_data()

html中第一行、第二行分别为<html>和<head>,后面无具体数据,只有回车换行,所以调用handle_data(),打印结果为换行;</html></head>同理。

3.一个简单的例子

获取豆瓣上正在上映影片的基本信息

# encoding=utf8
from urllib import request
import urllib
from html.parser import HTMLParser
from html.entities import name2codepoint


class Myparser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.movies = []

    def handle_starttag(self, tag, attrs):
        #此处得到的attrs即为根据tags解析出来的list,形式为[('属性1','值1'),('属性2','值2'),('属性3','值3')]
        def _attr(attrlist, attrname):
            #此函数用于后续通过查找某一属性来确定要找的标签
            for each in attrlist:
                if attrname == each[0]:
                    return each[1]
            return None

        if tag == 'li' and _attr(attrs, 'data-actors'):
            movie = {}
            movie['actors'] = _attr(attrs, 'data-actors')
            movie['director'] = _attr(attrs, 'data-director')
            movie['duration'] = _attr(attrs, 'data-dutation')
            movie['title'] = _attr(attrs, 'data-title')
            movie['rate'] = _attr(attrs, 'data-rate')
            self.movies.append(movie)


parser = Myparser()
url = 'https://movie.douban.com/'

if __name__ == '__main__':
    with urllib.request.urlopen(url) as f:
        data = f.read()#将url中内容全部读取出来
        parser.feed(data.decode('utf-8'))#将读取出来的内容解析
        for each in parser.movies:
            print('%(title)s|%(rate)s|%(actors)s|%(director)s|%(duration)s' % each)

结果如下:

runfile('D:/codes/python/20190226/test_douban.py', wdir='D:/codes/python/20190226')
阿丽塔:战斗天使 Alita: Battle Angel|7.6|罗莎·萨拉查 / 克里斯托弗·沃尔兹 / 基恩·约翰逊|罗伯特·罗德里格兹|None
三变山变|||彭兰玉|None
流浪地球|7.9|屈楚萧 / 吴京 / 李光洁|郭帆|None
飞驰人生|7.0|沈腾 / 黄景瑜 / 尹正|韩寒|None
疯狂的外星人|6.4|黄渤 / 沈腾 / 汤姆·派福瑞|宁浩|None
朝花夕誓 さよならの朝に約束の花をかざろう|7.0|石见舞菜香 / 入野自由 / 茅野爱衣|冈田磨里|None
一吻定情|5.3|王大陆 / 林允 / 陈柏融|陈玉珊|None
新喜剧之王|5.8|王宝强 / 鄂靖文 / 张全蛋|周星驰|None
熊出没·原始时代|6.5|张伟 / 张秉君 / 谭笑|丁亮|None
廉政风云 廉政風雲 煙幕|5.5|刘青云 / 张家辉 / 林嘉欣|麦兆辉|None
神探蒲松龄|4.1|成龙 / 阮经天 / 钟楚曦|严嘉|None
古井凶灵||程韦然 / 陈美林 / 李易芸|王辰六|None
今夜在浪漫剧场 今夜、ロマンス劇場で|7.2|绫濑遥 / 坂口健太郎 / 本田翼|武内英树|None
小猪佩奇过大年|4.0|朱亚文 / 刘芸 / 归亚蕾|张大鹏|None
白蛇:缘起|8.0|张喆 / 杨天翔 / 唐小喜|黄家康|None
大黄蜂 Bumblebee|7.1|海莉·斯坦菲尔德 / 小豪尔赫·兰登伯格 / 约翰·塞纳|特拉维斯·奈特|None
燃点|6.3|罗永浩 / 戴威 / 张颖|关琇|None
五十米之恋||谢楠 / 方力申 / 仇佩佩|李依理|None

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
python根据需求完成一个TXT解析器的简单开发 一 修改说明: 需求一: 一开始说要解析UECapabilityInfo 消息里的supportedBandCombination-r10 这个IE里的CA组合转化成易阅读的表现形式. 我以为一组CA组合就是一组: bandEUTRA-r10 ca-BandwidthClassUL-r10 ca-BandwidthClassDL-r10 supportedMIMO-CapabilityDL-r10 功能实现: 有效信息筛选:于是就用循环把UECapabilityInformation的数据里每一行作为一个元素放到list里面 然后用bandEUTRA-r10作为一组CA的识别信息、在筛选出同组ca-BandwidthClassUL-r10、ca-BandwidthClassDL-r10、supportedMIMO-CapabilityDL-r10的信息,添加保存到字符串中,然后再把字符串作为元素添加到list中去。最后遍历list的元素写入目标文件 需求二: 然后收到反馈CA组合的理解是错误的。一组CA组合应该是以大括号作为识别的,里面可能包含多组: bandEUTRA-r10: ca-BandwidthClassUL-r10 ca-BandwidthClassDL-r10 supportedMIMO-CapabilityDL-r10 CA组合识别原理:在查看UECapabilityInformation内的CA组合后 发现CA组合内第一个 bandEUTRA-r10因为比其他bandEUTRA-r10多了一层的CA组合的大括号,所以如果给每一行增加索引的话就会发现除了第一个bandEUTRA-r10,其他bandEUTRA-r10到上一个supportedMIMO-CapabilityDL-r10的距离都是一样的,为了减少复杂度,我删除了所有’{’,这样所有除了所有CA组合第一个bandEUTRA-r10往上第四行是’}’其他bandEUTRA-r10的往上第四行都是supportedMIMO-CapabilityDL-r10 功能实现: 添加索引:便利时用了for enumerate()循环,这样便利时可以在循环时,自动为每个元素生成索引 CA组合识别:在识别到bandEUTRA-r10时,增加一个判断if datalist1[index-4].startswith(),如果bandEUTRA-r10的往上第四行是supportedMIMO-CapabilityDL-r10说明同组CA未结束,把筛选的有效信息强制类型转换后添加在上个元素末尾,反之则说明是个新的CA组合,往列表里添加一个新的元素。 需求三: 之后收到反馈CA组合虽然识别了,但是排序不行,需要按照CA组合支持的band进行排序 功能实现: 排序:于是我在识别完CA组合后,增加了一个循环和count(),用CA组合里的’-’给它们归类 比如1AA,11A,21AA是一类;1A-1A,2A-1AA,3A-1A是一类 在用一个中间变量保存开头的band的数字,一个类中把开头支持band的数字字母相同的CA组合归为一行 比如1A-21A,1A-22A一类1AA-2AA 1AA-3AA为一类 需求四: 之后收到反馈,CA组合分类不能只按照开头比较分类,不然一但数据多了会对查阅带来极大不便,应该按照每组CA组合中bandEUTRA-r10的值进行判断,比如1AA-2AA,1A-2AA和1AA-2A应该归在同一行 实现原理:首先我想的是按位比较数字,但是因为字母的数量不稳定,数字的位置不一定对应,然后我就想把数字全部提取出来作为索引,在相应的索引后面添加同组元素,用dict来实现排序。难点就在于从字符串中提取数字。后来在python的正则表达式中找到相关的处理函数compile()(设置匹配对象类型)和findall()(找到所有匹配对象并以list返回)。 功能实现: 第二次排序:在上次的排序中我保留了分类和从小到大的排序。方便提取索引时,索引也是从小到大。每遍历一个元素(CA组合有效信息),就compile()和findall(),从该元素中提取数字组合(在compile()的参数中添加()就能够使提取的内容成为一组数据),然后通过dict自带函数setdefault()添加索引,并可以设置索引值为list类型(dict类型的索引的值不可变,但如果类型为list,list的内容可以进行改动),避免重复索引,在本次遍历中完成将元素添加到索引值对应的list中去 需求五: 之后对程序进行测试,在测试test2时发现layers增加了fourlayers类型后,用来代表layers的数字2和4会影响分类结果。比如1AA(2)-1AA(2)和1A(4)-1A(2)会被归为两类。 test1:当CA组合的格式为xx-xx-xx-xx-xx(最长可识别为五位元素的组合,再长就需要修改代码) test2:当CA组合包含fourLayers test3:当CA组合缺失某种格式比如xx-xx时发现layers增加了fourlayers 功能实现: : 解除layers对排序的影响:用II 和 IV替代2,4来表示layers,测试后不影响阅读与分类 二、整体程序架构: 1.通过循环和自带的startswith()先将每组CA组合的有效信息识别 2.通过sorted()函数将所有CA组合从小到大排列 3.通过count()函数将所有CA组合根据格式不同分类 4.通过循环和正则表达式的split()对所有CAlist数据进行处理(用split处理只是防止出现不必要的错误) 5.通过循环和正则表达式compile()和findall()识别所有CA组合中数字,并将同一组合中的数字合为一个元素(在同一循环,用这个数字的元素作为一个dict的索引),用dict自带的setdefault()进行Key的添加顺便设置Key的值为list,避免Key重复,在用append把当前Key的字符串,添加到Key对应值的list中去 6.最后对dict整体遍历,将每一个Key的值输出到文本中去。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值