zoukankan      html  css  js  c++  java
  • Python学习笔记(四十)— 内置模块(9)HTMLParser

    摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320023122880232500da9dc4a4486ad00426f081c15000

    如果要编写一个搜索引擎,第一步是用爬虫把目标网站的页面抓下来,第二步就是解析该HTML页面,看看里面的内容到底是新闻、图片还是视频。

    假设第一步已经完成了,第二步应该如何解析HTML呢?

    HTML本质上是XML的子集,但是HTML的语法没有XML那么严格,所以不能用标准的DOM或SAX来解析HTML。

    Python提供了HTMLParser来非常方便地解析HTML,只需简单几行代码:

    from html.parser import HTMLParser
    from html.entities import name2codepoint
    
    class MyHTMLParser(HTMLParser):
    
        def handle_starttag(self, tag, attrs):
            print('<%s>' % tag)
    
        def handle_endtag(self, tag):
            print('</%s>' % tag)
    
        def handle_startendtag(self, tag, attrs):
            print('<%s/>' % tag)
    
        def handle_data(self, data):
            print(data)
    
        def handle_comment(self, data):      # 解析评论
            print('<!--', data, '-->')
    
        def handle_entityref(self, name):    # 解析实体
            print('&%s:' % name)
    
        def handle_charref(self, name):
            print('&#%s:' % name)
    
    
    if __name__=='__main__':
        parser = MyHTMLParser()
        parser.feed('''<html>
        <head></head>
        <body>
        <!-- test html parser -->
            <p>Some <a href="#">html</a> HTML&nbsp;tutorial...<br>END</p>
        </body>
        </html>''')
        # HTML 中的常用字符实体是不间断空格(&nbsp;)。
        # 浏览器总是会截短 HTML 页面中的空格。如果您在文本中写 10 个空格,
        # 在显示该页面之前,浏览器会删除它们中的 9 个。如需在页面中增加空格的数量,
        # 您需要使用 &nbsp; 字符实体。

    结果:

    <html>
    
        
    <head>
    </head>
    
        
    <body>
    
        
    <!--  test html parser  -->
    
            
    <p>
    Some 
    <a>
    html
    </a>
     HTML tutorial...
    <br>
    END
    </p>
    
        
    </body>
    
        
    </html>

    feed()方法可以多次调用,也就是不一定一次把整个HTML字符串都塞进去,可以一部分一部分塞进去。

    特殊字符有两种,一种是英文表示的&nbsp;,一种是数字表示的&#1234;,这两种字符都可以通过Parser解析出来。

    小结

    利用HTMLParser,可以把网页中的文本、图像等解析出来。

    练习

    找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。

    # -*- coding: utf-8 -*-
    # 建议1: 子类在重载构造函数时不要忘了调用父类的构造函数
    # 建议2: HTMLParser的attrs是一个元素为tuple的list
    # 建议3: 调用类属性时,一定要加self, 否则相当于声明了新的临时变量
    
    from html.parser import HTMLParser
    from html.entities import name2codepoint
    from urllib import request
    
    class MyHTMLParser(HTMLParser):
    
        # 解析一下HTML,输出Python官网发布的会议时间、名称和地点。
        def __init__(self):
            super().__init__()
            self._event_title = []
            self._event_location = []
            self._event_time = []
            self._reading_title = False
            self._reading_time = False
            self._reading_location = False
    
        # 解析头标签
        def handle_starttag(self, tag, attrs):
            if tag == 'time':
                self._reading_time = True
            if len(attrs) >= 1:
                if tag == 'h3' and attrs[0][1] == 'event-title':
                    self._reading_title = True
                if tag == 'span' and attrs[0][1] == 'event-location':
                    self._reading_location = True
    
        # 解析内容
        def handle_data(self, data):
            if self._reading_title:
                self._event_title.append(data)
                self._reading_title = False
            if self._reading_time:
                self._event_time.append(data)
                self._reading_time = False
            if self._reading_location:
                self._event_location.append(data)
                self._reading_location = False
    
        @property
        def data(self):
            self._data = []
            for i in range(len(self._event_title)):
                dic = {}
                dic["title"] = self._event_title[i]
                dic["time"] = self._event_time[i]
                dic["location"] = self._event_location[i]
                self._data.append(dic)
            return self._data
    
    def getHtml():
        with request.urlopen('https://www.python.org/events/python-events/') as f:
            data = f.read().decode('utf-8')
        return data
    
    parser = MyHTMLParser()
    parser.feed(getHtml())
    for item in parser.data:
        print(str(item))

    结果:

    {'time': '07 Sept. – 11 Sept. ', 'location': 'Waseda University, Nishi-Waseda Campus, Building 63, Tokyo, Japan', 'title': 'PyCon JP 2017'}
    {'time': '08 Sept. – 11 Sept. ', 'location': 'Universidade de Caxias do Sul (UCS), Caxias do Sul, Rio Grande do Sul, Brazil', 'title': 'Python Sul'}
    {'time': '15 Sept. – 17 Sept. ', 'location': 'Lagos, Nigeria', 'title': 'PyCon Nigeria 2017'}
    {'time': '21 Sept. – 25 Sept. ', 'location': 'Toulouse, France', 'title': 'PyCon FR 2017'}
    {'time': '22 Sept. – 25 Sept. ', 'location': 'Caceres, Spain', 'title': 'PyConES17'}
    {'time': '28 Sept. – 30 Sept. ', 'location': 'United States International University, Nairobi, Kenya', 'title': 'PyConKE 2017'}
    {'time': '28 Aug. – 02 Sept. ', 'location': 'Erlangen, Germany', 'title': 'EuroSciPy 2017'}
    {'time': '26 Aug. – 28 Aug. ', 'location': 'Kuala Lumpur, Malaysia', 'title': 'PyCon APAC 2017'}
  • 相关阅读:
    智器SmartQ T7实体店试用体验
    BI笔记之SSAS库Process的几种方案
    PowerTip of the Day from powershell.com上周汇总(八)
    PowerTip of the Day2010071420100716 summary
    PowerTip of the Day from powershell.com上周汇总(十)
    PowerTip of the Day from powershell.com上周汇总(六)
    重新整理Cellset转Datatable
    自动加密web.config配置节批处理
    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable
    在VS2003中以ClassLibrary工程的方式管理Web工程.
  • 原文地址:https://www.cnblogs.com/douzujun/p/7466343.html
Copyright © 2011-2022 走看看