HTML Tag Selector标签选择器设计(手稿PFC0200512)

用惯了xpath、scrapy或jsoup这类HTML 文档解析器,今天决定试试实现其tag selector标签选择器。

HTML是一个规范的文档。一般来说,HTML文档是对称闭合的,跟XML文档很相似,但不是严格的。HTML tag标签一般由“<”、“>”包围,标签开始符基本要素为左右尖括号界定符、tag标签名、tag标签属性和tag标签属性值,表达式为:<[tag name] [tag attribute name]=”[tag attribute value]”>,标签结束符表达式为:</[tag name]>。其中,tag标签属性和值为非必要。标签属性和值的赋值表达式为:[属性]=”[值]”或[属性]=[值]两种,一般推荐前者的使用方法。属性赋值表达式之间使用空格分隔。

HTML标签具有规范的属性,也可以自定义属性。自定义属性可以保存一定的数据,不能被标准的HTML解释器识别。一般情况下,优先考虑标准HTML的实现。

HTML文档解析器本质上是语法树的一种实现,简单来说,根据特定的标签词汇和语法规则实现对HTML文档的解析处理。底层的语法树一般是使用类似于递归的处理方法。像函数递归和快速排序都是很有意思的语法规则设计。都是使用简短的语句实现人的智慧精华。说了这么多,下面来试试从高级语言层面实现标签选择器。这里笔者主要是通过正则表达式来完成其实现。

标签选择器最基本的是标签的识别。前面提到,标签开始符和结束符的表达式分别为:<[tag]>、</[tag]>,[tag]为由英文字母组成的标签名。对应正则表达式:

<python>
 
tag_start_pattern=’<tag>’
 
tag_end_pattern=’</tag>’
 
</python>

标签属性赋值表达式为:[ ][attribute]=”[value]”,对应正则表达式:

<python>
tag_attribute_pattern=’[ ][attribute][=][“][value][“]’
</python>

应用模式除包含上述表达式外,还需进行标签最小配对或标签对称等优化。

以下是实现代码的草稿:

<python>
 
# -*- coding: UTF-8 -*-
 
# !/usr/bin/env python
 
'''
author: MRN6
blog: qq_21264377@blog.csdn.net
'''
 
import re
 
 
#定义path规则
 
def qpath(path=None, html=None):
 
    if path is None or html is None:
 
        return  []
 
    rules=path.split("//")
 
    matches=""
 
    for rule in rules:
 
        if len(rule.strip())<1:
 
            continue
 
        ruledatas=rule.split(':')
 
        tag=ruledatas[0]
 
        attributedatas=ruledatas[1].split('=')
 
        attribute=attributedatas[0]
 
        value=attributedatas[1]
 
        print('<'+tag+' '+attribute+'="'+value+'"')
 
        rules=len(ruledatas)
 
        if rules==2:
   
            matches=re.findall('(<'+tag+'[^<>]*'+attribute+'="'+value+'[^"]*"[^<>]*>((?!<'+tag+'[^<>]*'+attribute+'="'+value+'"[^<>]*>).)*</'+tag+'>$)', html, re.M|re.S|re.I)
 
        elif rules==3 and ruledatas[2]=='END':
 
            matches=re.findall('(<'+tag+'[^<>]*'+attribute+'="'+value+'[^"]*"[^<>]*>((?!</'+tag+'>).)*</'+tag+'>$)', html, re.M|re.S|re.I)
 
            #注:参考https://blog.csdn.net/iteye_13785/article/details/82638686
 
        #检查标签对称问题
 
        if len(matches)>0:
 
            for match in matches:
 
                smatches=re.findall('<'+tag, match[0], re.M|re.S|re.I)
 
                ematches=re.findall('</'+tag+'>', match[0], re.M|re.S|re.I)
 
                slen=len(smatches)
 
                elen=len(ematches)
 
                if slen!=elen:
 
                    print(match[0]+' greedy match: '+str(slen)+'-'+str(elen))
 
    return matches
 
 
 
html='''
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<title>标题</title>
</head>
<body>
    <div id="root">
        <div class="content-item first">
            <div class="content-title">title1</div>
            <div class="content-body">content1</div>
        </div>
        <div class="content-item">
            <div class="content-title">title_2</div>
            <div class="content-body">content2</div>
        </div>
        <div>&nbsp;</div>
        <div class="content-item">
            <div class="content-title">title3_</div>
            <div class="content-body">content3</div>
        </div>
</div>
<div>&nbsp;</div>
</body>
</html>
'''
 
mypath="//div:id=root//div:class=content-item"
 
mypath2="//div:id=root//div:class=content-item//div:class=content-title:END"
 
results=qpath(mypath, html)
 
print(len(results))
 
for result in results:
 
    print(result)
 
 
 
results2=qpath(mypath2, html)
 
print(len(results2))
 
for result in results2:
 
    print(result)
 
</python>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352