之前写过两篇关于HTML DOM解析的文章(附代码):

[PFC020071401](https://www.jianshu.com/p/46c92333e2c8)

[PFC0200512](https://www.jianshu.com/p/0a3603993864)

第一篇只能识别简单的HTML标签包含,第二篇仅可以分析出一组根叶子节点(Leaf Node),距离简单的标签选择器还有较大的差距。后来想了一两天,结合第二篇PFC020071401里的最小标签对称法,决定放弃完全依赖正则表达式的想法。最终考虑像进行语法分析那样,从HTML文本中,分离出一棵或多颗的语法树,从语法树中找出最终目标。

当前的想法是:

1)分析路径语法;

2)对HTML文本进行正则表达式匹配,找到目标标签;

3)使用最小标签对称法,循环匹配出所有的结果树;

4)判断当前标签是否为最终目标标签,是则利用第3)步结果进行步骤1),否则5);

5)列出结果。

最小标签对称法是利用HTML标签的开始标记和结束标记对称的原理,来完成标签完整性的目标的方法。对于某些个别标签开始和结束标记不完全对称的问题另当别论。HTML5基本要求标签对称。这样就可以忽略正则表达式贪婪匹配带来的“多重包含问题”--标签不完整、包含多个匹配结果。看以下代码最小对称法 minimalpair():

'''

author: MRN6

blog: qq_21264377@blog.csdn.net

updated: Jul. 18th, 2020 Sat. 03:40PM

'''

def minimalpair(tag, html, position):

#最小对称法

check_start_tag='

check_end_tag=''

if tag=='meta':

check_end_tag='>'

else:

check_end_tag=''+tag+'>'

start_tag_length=len(check_start_tag)

end_tag_length=len(check_end_tag)

length=len(html)

index=position

start=html.find(check_start_tag, index)

if start>=0:

require=1

while require>0 and (index

index=index+1

if html[index:index+start_tag_length]==check_start_tag:

require=require+1

if html[index:index+end_tag_length]==check_end_tag:

require=require-1

return html[position:index+end_tag_length]

image.gif

这个是从第二篇里的symmetry()方法修改而来, 第2个参数修改为html文本, 增加第3个参数position索引。

qpath()方法修改为match(),语法分析中去除“END”属性标记:

'''

author: MRN6

blog: qq_21264377@blog.csdn.net

updated: Jul. 18th, 2020 Sat. 03:40PM

'''

def match(path=None, html=None):

if path is None or html is None or len(path.strip())<=0 or len(html.strip())<=0:

return []

if not '//' in path:

return []

rules=path.split('//')

matches=[]

submatches=[]

l=len(rules)

c=0

match_html=html

for rule in rules:

c=c+1

if len(rule.strip())<1:

continue

if submatches is not None and len(submatches)>0:

t=submatches

submatches=[]

for submatch in t:

if len(submatch.strip())<=0:

continue

attributecontent=''

if ':' in rule:

ruledatas=rule.split(':')

tag=ruledatas[0]

attributedatas=ruledatas[1].split('=')

attribute=attributedatas[0]

value=attributedatas[1]

attributecontent=attribute+'="'+value+'[^"]*"'

else:

tag=rule

tempmatches=re.findall(']*'+attributecontent, submatch)

if tempmatches is None or tempmatches==[]:

continue

index=0

#print('[match-end]', tempmatches, '[/match-end]')

for tempmatch in tempmatches:

position=submatch.find(tempmatch, index)

while position>=0 and index

match=minimalpair(tag, submatch, position)

index=position+len(match)

if c==l:

matches.append(match)

else:

submatches.append(match)

position=submatch.find(tempmatch, index)

else:

attributecontent=''

attribute=None

value=None

if ':' in rule:

ruledatas=rule.split(':')

tag=ruledatas[0]

attributedatas=ruledatas[1].split('=')

attribute=attributedatas[0]

value=attributedatas[1]

attributecontent=attribute+'="'+value+'[^"]*"'

else:

tag=rule

tempmatches=re.findall(']*'+attributecontent, match_html)

if tempmatches is None or tempmatches==[]:

return []

index=0

#print('[match-root]', tempmatches, '[/match-root]')

for tempmatch in tempmatches:

if not tag in tempmatch or (attribute is not None and value is not None and not attribute+'="'+value+'"' in tempmatch):

continue

position=match_html.find(tempmatch, index)

while position>=0 and index

match=minimalpair(tag, match_html, position)

#print(position, '[match-sub]', match, '[/match-sub]')

index=position+len(match)

if c==l:

matches.append(match)

else:

submatches.append(match)

position=match_html.find(tempmatch, index)

return matches

对path和html进行简单有效性检查后,分析path的语法,得出path的结构。对path进行逐级拆分,并在html内容中进行匹配。首次分析的HTML内容为完整的html。之后每次分析的HTML内容为前一次分析出的语法树submatches。因为每次分析的结果皆采用最小对称法,所以避免重复包含和标签不完整的问题。分析流程抵达最后目标标签时,将结果加入matches中,最后返回matches。

现在用实践来检验一下成果。

https://news.163.com HTML源码

https://news.163.com HTML源码

输入路径规则:

mypaths=["//div:class=column_main//h3", "//div:class=column_main//div:class=photo", "//div:class=column_main//ul//li",

"//div:class=bd", "//div:class=bd//div:class=ns_area list", "//div:class=bd//div:class=ns_area list//li",

"//div:class=bd//div:class=ns_area list//ul//li//a", "//div:class=bd//div:class=ns_area list//ul//a",

"//div:class=ntes-quicknav-content//ul//li", "//div:class=ntes-quicknav-content//ul//li//a",

"//div:class=mt35 mod_hot_rank clearfix//ul//li", "//div:class=mt35 mod_hot_rank clearfix//ul//a",

"//div:class=mt35 mod_money//ul//li", "//div:class=mt35 mod_money//div:class=bg//h3",

"//div:class=bottomnews_main clearfix//h2",

"//div:class=ns_area index_media//ul//li//a",

"//meta:http-equiv=Content-Type",

"//meta:name=keywords",

"//title"]

这些都是该HTML文本内容中存在的规则,包含逐级和跳级的。任意选取其一进行测试。

path=mypaths[-10]

results=match(path, html)

print('', path, '')

print('', str(len(results)), '')

counter=0

for result in results:

counter=counter+1

print('['+str(counter)+']', result, '[/'+str(counter)+']')

mypaths[-10]为mypaths数组中倒数第10个,这是python的基本语法。

运行结果:

path=mypaths[-10]运行结果

html 选中tag标签,HTML Tag Selector标签选择器PFC020071801相关推荐

  1. js实现3d标签云tag动画效果js特效代码

    下载地址JS制作TAG标签云文字动画特效是一款当鼠标悬停某个标签时,当前标签静止,移出恢复滚动效果.tagcloud({ selector: ".tagcloud", //元素选择 ...

  2. GIT中打标签(tag)的意义

    在git代码管理时,有时候我们想对某个特定的commit 添加标记,比如要标识版本信息,这时候就可以用的git中的打标签功能.打tag就类似于我们看书放书签一样,以后可以直接用tag找到提交的位置,不 ...

  3. 【Git】Git 标签使用 ( 查询哈希码 | 创建标签 git tag v1.0 | 查询标签 git tag | 查询标签信息 git show v1.0 | 创建标签并指定说明 | 删除标签 )

    文章目录 一.查询提交记录哈希码 1.git log --pretty=oneline --abbrev-commit 2.git reflog 二.为某个提交设置标签 git tag v1.0 23 ...

  4. git命令之git tag 给当前分支打标签

    git tag - 标签相关操作 发表于 2011年06月29日 由 机器猫 标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ git tag # 在控制台打印出当前仓库的所有标签 ...

  5. Git打标签(Tag)(亲测)

    做个笔记记录下来以备自己忘记 列出所有标签 git tag 通配符过滤标签 git tag -l "v1.0.0-RC5*" 新建tag git tag tagName 创建带备注 ...

  6. Git 标签(tag)相关操作

    前言 通过该文你将了解到如何 Git 本地仓库以及远程仓库 tag 标签的增删改查操作. 什么是标签? Git 的标签我们可以理解成一个项目管理中的里程碑,在开发中我们可以通过标签将一些写好的功能做一 ...

  7. 【IDEA】出现 Wrong tag ‘Author_‘ 错误的 Author 标签等的黄色警告问题

    问题描述 设置自动生成注解后,会产生 Wrong tag 'Author:' 错误的 Author 标签等的黄色警告问题 解决方案: 配置路径: File --> NewProjects Set ...

  8. 怎样自己定制标签(Custom Tag)

    怎样自己定制标签(Custom Tag)  (整理的学习笔记)  步骤1.创建一个Tag handler class(标记处理器类)  package  javax.servlet.jsp.tagex ...

  9. 【Unity学习笔记】标签(Tag)和层(Layer)

    声明:此篇文章是个人学习笔记,并非教程,所以内容可能不够严谨.可作参考,但不保证绝对正确.如果你发现我的文章有什么错误,非常欢迎指正,谢谢哦. 此篇文章是根据官网手册总结:https://docs.u ...

  10. Docker 拉取镜像及标签 pull | tag

    Docker 拉取镜像及标签 pull | tag 重翻Fabric项目的源码,发现Docker部分内容,有很多不尽理解的地方,看着看着,就看到使用docker pull拉取Fabric镜像及使用do ...

最新文章

  1. python软件开发-有哪些值得推荐的 Python 开发工具?
  2. boost::callable_traits的remove_varargs_t的测试程序
  3. Servlet之间的跳转
  4. 能过好每一天的人,都不会混得太差
  5. python中pprint是干什么的_Python中的pprint折腾记
  6. SQL注入攻击防御深层思考
  7. MongoDB学习——介绍一款MongoDB连接管理工具
  8. 验证世界各地区手机号码libphonenumber
  9. 【转】支持向量机回归模型SVR
  10. Mysql 查询根节点下所有叶子节点
  11. 孟云飞 :一代通才 自成家数——赵之谦的艺术人生
  12. 小程序倒计时显示晃动问题
  13. 2013年01月06日
  14. springboot+vue房屋租赁系统-求租合同系统java
  15. DNS解析域名解析过程
  16. 如本科技上海分公司乔迁新址,加速长三角地区的业务覆盖
  17. Excel如何利用函数删除数据中空格
  18. 感悟+北京and新疆知识点
  19. Numbers Mac表格的功能与介绍
  20. 猴子摘香蕉问题-人工智能模拟

热门文章

  1. 微信小程序退出页面时清除定时器
  2. 通信协议——HTTP、TCP、UDP
  3. linux下的定时任务处理
  4. java面试mysql的引擎_面试官:你用过mysql哪些存储引擎,请分别展开介绍一下
  5. mysql查询建表SQL语句
  6. 【maven】仓库的优先级顺序
  7. BufferedReader和FileReader的区别
  8. 中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext
  9. 格力机器人图解_格力工业机器人:是时候展示真正的实力了
  10. python argparse type_python argparse(参数解析模块)