zoukankan      html  css  js  c++  java
  • 写python代码的一点感想

    记得之前写过一篇文章,html2javaben,并发布了一个相关的组件,大概的功能就是把抓取的html页面后抽取其中的结构化数据进行二次加工。最近在用python也在写一个好玩的抓取网页的东西,也想封装一个python版的这样的组件用,想不到前后大概花了2个小时构思,2个小时编码就搞定了。想起了以前用java写这个东西时,总是免不了最后出来的东西让你特别有“成就感”,看这包名结构就知道了,呵呵。

    现在就用python去实现这个功能,感受下这个愉快的过程.

    我们还是以之前文章中的html代码做为示例:

    <table style="height: 306px;  99%;">
        <tr>
            <th style=" 100px;" align="left">
                姓名:</th>
            <td>
                <span id="lblName">tony</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                员工编号:</th>
            <td>
                <span id="lblWork">ite00395</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                性别:</th>
            <td>
                <span id="lblSex">man</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                Email:</th>
            <td>
                <span id="lblEmail">lihf@gggg.com</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                MSN:</th>
            <td>
                <span id="lblMsn"> lhf@hotmail.com</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                公司电话:</th>
            <td>
                <span id="lblPhone">13712548548</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                移动电话:</th>
            <td>
                <span id="lblMobile">1371489634</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                所属部门:</th>
            <td valign="middle">
                <span id="lblDepartment">P后台项目组</span>
            </td>
        </tr>
        <tr>
            <th align="left">
                部门地址:</th>
            <td valign="middle">
                <span id="lblDeptAddress"></span>
            </td>
        </tr>
    </table>

    现在我们需要抽取的数据是这样的格式:

    {'Name':'tony',
    'Work':'ite00395',
    'Sex':'man',
    'Email':'lihf@gggg.com',
    'Msn':'lhf@hotmail.com',
    'Phone':'13712548548',
    'Mobile':'Mobile',
    'Department':'P后台项目组',
    'DeptAddress':''} 

     我希望封装的解析组件能完成如下的代码:

    html_regular = {'Name':r'<span id="lblName">(.+?)</span>',
                    'Work':r'<span id="lblWork">(.+?)</span>',
                    'Sex':r'<span id="lblSex">(.+?)</span>',
                    ........}
    HtmlParser(html_regular).parse(html)

    上面两句代码的意思很明确:第一句代码是定义了html字符中我们待抽取的结构化数据的组织形式,即通过什么样的正则表达式去把这些数据匹配出来。第二句代码就是构造一个解析器去解析指定的html参数,输出我们想要的结构化数据.

    对于比较复杂的数据结构,如List对象,嵌套对象,等等,我们也要提供支持。

    list_regular = [{'groupKey':r'在html源码中分隔List数据的分隔符代码'},
                    {'description':r'匹配description的正则表达式',
                     'date':r'匹配date的正则表达式'}]

    以上结构是抽取List重复数据时的表达式定义:List中必需有且只有两个元素,第一个'groupKey'是对当前List结构在Html源码中的分隔字符,第二个元素是List组成元素的正则表达式匹配描述。

    还是以前面的Html源码举例,如果现在的Html中有多个这个的数据:

    <table style="height: 306px;  99%;">
        <tr>
            <th style=" 100px;" align="left">
                姓名:</th>
            <td>
                <span id="lblName">tony1</span>
            </td>
        </tr>
        ....
        ....
        ....
    </table>
    <table style="height: 306px;  99%;">
        <tr>
            <th style=" 100px;" align="left">
                姓名:</th>
            <td>
                <span id="lblName">tony2</span>
            </td>
        </tr>
        ....
        ....
        ....
    </table>  
    <table style="height: 306px;  99%;">
        <tr>
            <th style=" 100px;" align="left">
                姓名:</th>
            <td>
                <span id="lblName">tony3</span>
            </td>
        </tr>
        ....
        ....
        ....
    </table>

    可以看到这里的结构就是List,且有三个元素数据。所以这时的regular表达式应该这样描述:

    list_regular = [{'groupKey':r'<table style="height: 306px;  99%;">'},
                    {'Name':r'<span id="lblName">(.+?)</span>',
                       ...}]

    以上描述完了我们希望的这个组件所具有的功能后,我们再看下具体的实现代码:

     1 # encoding: utf-8
     2 
     3 import re
     4 
     5 """
     6 Translate string of html to obj by specified regular
     7 """
     8 
     9 class HtmlParser():
    10     def __init__(self,regular):
    11         self.regular = regular
    12 
    13     def parse(self,html):
    14         return parseNode(self.regular,html)
    15 
    16 
    17 def processReg(exp,html):
    18     p = re.compile(exp,re.DOTALL)
    19     m = p.search(html)
    20     if m:
    21         try:
    22             return m.group(1).strip()
    23         except IndexError:
    24             pass
    25 
    26 
    27 
    28 
    29 def parseNode(node,html):
    30     if type(node) is list:
    31         objList = []
    32         for itemStr in getSubHtmlGenerator(node[0]['groupKey'],html):
    33             objList.append(parseNode(node[1],itemStr))
    34         return objList
    35     else:
    36         obj = {}
    37         for name,regular in node.items():
    38             if type(regular) is str:
    39                 obj[name] = processReg(regular,html)
    40             else:
    41                 obj[name] = parseNode(regular,html)
    42         return obj
    43 
    44 
    45 
    46 def getSubHtmlGenerator(groupKey,html):
    47     while True:
    48         start = html.find(groupKey)
    49         if start != -1:
    50             end = html[start+len(groupKey):].find(groupKey)
    51             if end!= -1:
    52                 yield html[start:end + start + len(groupKey)]
    53                 html = html[end+start+len(groupKey):]
    54             else:
    55                 yield html[start:]
    56                 break
    57         else:
    58             break

    可以看到,包括注释加空行,总共58行代码,如果大家遇到过这样的需求和看过上面所写的这些,应该知道这58行代码所做的事,是不是很简单?

    总结:
    我写这篇文章不是说想介绍我写的这个组件,因为它都称不上一个组件,只是写了一个类,提供了一个方法。我真正的想说的是python这个语言所强在的东西,数据结构即代码,所写的,即是所表达的意思,简单清晰。

    原创文章,转载请注明出处,谢谢!

  • 相关阅读:
    mysqlbinlog基于某个偏移量进行数据的恢复(重做),--start-position,--stop-position的使用方法
    mysql数据库binary log中的事件到底是什么?
    mysqlbinlog工具的作用是什么呢,如何将binary log转换为文本格式?
    mysqldump对于DB进行逻辑备份的时候,是否会备份视图呢?
    mysqldump工具,通过--where选项,导出指定表中指定数据?
    mysql数据库中,通过mysqladmin工具,创建数据库
    mysql数据库中,查看某个数据库下的表的存储类型都有哪些
    Oracle体系结构之rac内存管理
    Oracle HA 之 Server Pool 实战
    Oracle HA 之 SERVICE和DRM实战
  • 原文地址:https://www.cnblogs.com/jcli/p/2942935.html
Copyright © 2011-2022 走看看