html 选中tag标签,HTML Tag Selector标签选择器PFC020071801
之前寫過兩篇關(guān)于HTML DOM解析的文章(附代碼):
[PFC020071401](https://www.jianshu.com/p/46c92333e2c8)
[PFC0200512](https://www.jianshu.com/p/0a3603993864)
第一篇只能識(shí)別簡(jiǎn)單的HTML標(biāo)簽包含,第二篇僅可以分析出一組根葉子節(jié)點(diǎn)(Leaf Node),距離簡(jiǎn)單的標(biāo)簽選擇器還有較大的差距。后來想了一兩天,結(jié)合第二篇PFC020071401里的最小標(biāo)簽對(duì)稱法,決定放棄完全依賴正則表達(dá)式的想法。最終考慮像進(jìn)行語法分析那樣,從HTML文本中,分離出一棵或多顆的語法樹,從語法樹中找出最終目標(biāo)。
當(dāng)前的想法是:
1)分析路徑語法;
2)對(duì)HTML文本進(jìn)行正則表達(dá)式匹配,找到目標(biāo)標(biāo)簽;
3)使用最小標(biāo)簽對(duì)稱法,循環(huán)匹配出所有的結(jié)果樹;
4)判斷當(dāng)前標(biāo)簽是否為最終目標(biāo)標(biāo)簽,是則利用第3)步結(jié)果進(jìn)行步驟1),否則5);
5)列出結(jié)果。
最小標(biāo)簽對(duì)稱法是利用HTML標(biāo)簽的開始標(biāo)記和結(jié)束標(biāo)記對(duì)稱的原理,來完成標(biāo)簽完整性的目標(biāo)的方法。對(duì)于某些個(gè)別標(biāo)簽開始和結(jié)束標(biāo)記不完全對(duì)稱的問題另當(dāng)別論。HTML5基本要求標(biāo)簽對(duì)稱。這樣就可以忽略正則表達(dá)式貪婪匹配帶來的“多重包含問題”--標(biāo)簽不完整、包含多個(gè)匹配結(jié)果。看以下代碼最小對(duì)稱法 minimalpair():
'''
author: MRN6
blog: qq_21264377@blog.csdn.net
updated: Jul. 18th, 2020 Sat. 03:40PM
'''
def minimalpair(tag, html, position):
#最小對(duì)稱法
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
這個(gè)是從第二篇里的symmetry()方法修改而來, 第2個(gè)參數(shù)修改為html文本, 增加第3個(gè)參數(shù)position索引。
qpath()方法修改為match(),語法分析中去除“END”屬性標(biāo)記:
'''
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
對(duì)path和html進(jìn)行簡(jiǎn)單有效性檢查后,分析path的語法,得出path的結(jié)構(gòu)。對(duì)path進(jìn)行逐級(jí)拆分,并在html內(nèi)容中進(jìn)行匹配。首次分析的HTML內(nèi)容為完整的html。之后每次分析的HTML內(nèi)容為前一次分析出的語法樹submatches。因?yàn)槊看畏治龅慕Y(jié)果皆采用最小對(duì)稱法,所以避免重復(fù)包含和標(biāo)簽不完整的問題。分析流程抵達(dá)最后目標(biāo)標(biāo)簽時(shí),將結(jié)果加入matches中,最后返回matches。
現(xiàn)在用實(shí)踐來檢驗(yàn)一下成果。
https://news.163.com HTML源碼
?
https://news.163.com HTML源碼輸入路徑規(guī)則:
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文本內(nèi)容中存在的規(guī)則,包含逐級(jí)和跳級(jí)的。任意選取其一進(jìn)行測(cè)試。
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數(shù)組中倒數(shù)第10個(gè),這是python的基本語法。
運(yùn)行結(jié)果:
path=mypaths[-10]運(yùn)行結(jié)果
總結(jié)
以上是生活随笔為你收集整理的html 选中tag标签,HTML Tag Selector标签选择器PFC020071801的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络技术发源于什么,计算机网络基础
- 下一篇: 11-selenium浏览器自动化