首先需要声明 html 不能用正则表达式来直接匹配进行内容抽取等处理,这样做的结果很严重
!
Not XHTML Parser
另一点需要注意的是:不是构建 xhtml parser ,如果是 xhtml 的话可采用 parser generator 根据 grammar
直接生成解析器即可,而 html 由于对错误很宽容(比如普遍的标签不闭合问题),具备超强的错误纠正机制,简单的自动 parser 生成并不可行。也即 html 不是一种上下文无关
的语言。
对 html parser 构建有两个思路:
一个思路是半自动生成,先由自动生成的 parser
识别出可以识别的标签,后期再手动匹配标签
,但这种方法对于本身标签都不完整的情况不能正确识别:
<div id='n
另一个思路就是完全手写 parser ,递归下降进行 dom 树建立,这其中可以加入很多容错处理,例如 html5 的 parse
规则。
Write Parser By Hand
手写 parser 从两方面来考虑:
1. tag/node 的识别。难点在于 tag 的识别:收集 tag 对应的属性以及属性值。其中词法识别过程可以采用正则表达式来识别标签名,属性名,属性值,不过为了更好的容错以及信息收集,也可以直接采用确定有穷状态机来识别。语法部分就比较简单,将成对的属性名和属性值和标签名关联起来成为 Tag 对象即可。
通过 1 可以识别出独立的开标签,闭标签,其他节点元素(text,comment)序列。
2. dom 树建立。在该步穿插调用 1 ,将配对的开闭标签组合成为一个 dom 节点。注意点在于
2.1 rawtext/rcdata 的处理:当遇到 textarea ,script,style 时,其后内容的 parse 不能简单的调用 1 步,需要特殊识别对应的结束标记来结束 textarea/syle/script。例如:防止用户输入以下代码意外结束或开始标签(本质上是不符合html5 parse 规范,,规范中说明遇到结束标签会检查下结束标签是不是和当前的开始标签相同,而对 script 即是检查 xx 是不是等于 script (</xx>)):
<textarea>
<div>
x
</div>
</textarea>
<script>alert("<div></div>");</script>
2.2 标签闭合问题:当遇到结束标签不和当前开始标签相同,或到了parse 结尾时尚有开标签未闭合。例如:
<div>
<div>
<span>
2
</div>
或
<div>1
这时就需要自动补全闭合标签,对在当前递归分析栈上的开标签元素依次弹出闭合,直到当前结束标签和某个栈上的开标签名称相同或者栈中元素为空。不能匹配的闭标签做抛弃处理。
2.3 修正 html 代码(optional)。如果需要对输出代码的质量进行控制(主要指标签嵌套检查),那么就需要在每个节点 parse 完毕后进行修正后处理(post-process),例如:
<a href='g.cn'>
<div>
1
<span>
3
</span>
<a href='z.cn'>
4
</a>
2
</div>
</span>
修正后的 dom 树对应的 html 为:
<div>
<a href='g.cn'>1
<span>
3
</span>
</a>
<a href='z.cn'>
4
</a>
<a href='g.cn'>
2
</a>
</div>
将嵌套关系错误的元素正确应用到真正需要的对应节点上去。具体对于行内元素 a 包含块状元素 b 的情况,那么该行内元素 a 就需要递归嵌套到块状元素 b 的所有行内元素上去(注意消重)。而对于
<div><li>1</li>
<li>2</li>
</div>
则需要生成固定的父元素标签 ul:
<ul>
<li>
1
</li>
<li>
2
</li>
</ul>
Scenario
常见的应用场景包括: html 代码美化与压缩,高效客户端过滤,规范,检测用户输入的 html (dom-free)。
具体到压缩处理
又包含
去除默认属性,
合并连续空白,
去除注释,
属性值引号/属性值条件去除,
闭合闭合标签(</body> </html></option> </li>)条件去除
...
而这一切都是在 parse 后进行。
DEMO
html 代码美化与压缩
分享到:
相关推荐
static Parser createParser(String html, String charset)方法用于创建一个Parser对象,并解析指定的HTML字符串。 示例代码 下面是一个使用Parser中文API解析HTML网页的示例代码: ```java import java.io....
parser.write(html); parser.end(); } const inputHTML = ` <html> <p class="intro">Hello, world! <p id="greeting">Welcome to Node.js! </html> `; parseHTML(inputHTML); ``` 在这个例子中,我们创建...
myApp := app.NewWithID("html-parser") myWindow := myApp.NewWindow("HTML到文本转换器") ``` 3. **设计用户界面**:创建输入框让用户输入HTML代码,一个按钮触发解析,以及一个文本区域显示结果。 ```go ...
f.write(parser.html()) # 将解析后的HTML转换为字符串 ``` `HARSER`库的灵活性和易用性使其成为Python开发者处理HTML文档的有力工具。它不仅简化了HTML解析过程,还使得XPath的使用变得直观。对于初学者和经验...
BeautifulSoup库依赖于一个解析器,通常我们使用`lxml`或`html.parser`。确保你也安装了`lxml`: ```bash pip install lxml ``` 接下来,我们将探讨如何通过Python和BeautifulSoup实现给HTML文件的a标签添加属性。...
soup = BeautifulSoup(response.content, "html.parser") urls = [li.a['href'] for li in soup.find_all("li")] # 假设URL在li标签中 return urls # 保存HTML文件 def save_html_to_file(url, filename): ...
soup = BeautifulSoup(html_content, 'html.parser') text_without_tags = soup.get_text() ``` 如果源代码还提供了对字符串的处理,那么可能会有直接对HTML片段进行处理的函数。这通常涉及字符串操作,如正则...
This is an agile HTML parser that builds a read/write DOM and supports plain XPATH or XSLT (you actually don't HAVE to understand XPATH nor XSLT to use it, don't worry...). It is a .NET code library ...
soup = BeautifulSoup(f, 'html.parser') txt = soup.get_text() with open('output.txt', 'w') as f: f.write(txt) ``` - **JavaScript**:使用DOM API读取HTML内容,然后使用正则表达式去除HTML标签。这可以...
This is an agile HTML parser that builds a read/write DOM and supports plain XPATH or XSLT (you actually don't HAVE to understand XPATH nor XSLT to use it, don't worry...). It is a .NET code library ...
首先,我们需要导入BeautifulSoup库和一个HTML解析器,如`lxml`或内置的`html.parser`: ```python from bs4 import BeautifulSoup import lxml ``` 然后,我们可以读取磁盘上的HTML文件并用BeautifulSoup解析: ...
Files.write(outputFile.toPath(), summary.toString().getBytes(StandardCharsets.UTF_8)); ``` 以上就是使用HTMLParser库截取HTML摘要的基本步骤。请注意,这只是一个基础示例,实际应用中可能需要根据网页结构...
soup = BeautifulSoup(response.text, 'html.parser') with open('output.html', 'w', encoding='utf-8') as f: f.write(soup.prettify()) ``` 这段代码首先发送GET请求到指定的URL,然后使用BeautifulSoup解析...
Parser parser = new Parser(reader); ``` 4. **转换为XHTML**:NekoHTML本身并不直接提供将HTML转换为XHTML的功能,但你可以通过遍历DOM并手动调整元素和属性来实现。例如,确保所有的属性值都用引号括起来,...
soup = BeautifulSoup(f.read(), 'html.parser') table = soup.find('table') if not headers: ths = table.find_all('th') headers.extend([th.text.strip().replace('\n', '') for th in ths]) for tr in ...
soup = BeautifulSoup(content, 'html.parser') text = soup.get_text() ``` 这段代码会打开一个HTML文件,使用BeautifulSoup解析内容,然后提取出所有文本。 另一个可能使用的库是lxml,它是一个速度非常快的HTML...
soup = BeautifulSoup(html_content, 'html.parser') ``` 有了soup对象,我们可以通过CSS选择器或者方法来找到我们需要的元素。例如,如果我们想要获取所有帖子的标题,可以这样做: ```python titles = soup.find...
soup = BeautifulSoup(html_content, 'html.parser') ``` 3. **提取HTML标签文本**:BeautifulSoup提供了多种方法来搜索和提取HTML标签的文本。例如,我们可以使用`.find_all()`方法找到所有的`<p>`标签,然后使用`....
Files.write(Paths.get("output.html"), doc.html().getBytes(), StandardOpenOption.CREATE); // 保存到文件 ``` 除了Jsoup,HtmlUnit是一个更全面的库,它模拟了一个完整的浏览器,支持JavaScript执行和网络...
soup = BeautifulSoup(response.text, 'html.parser') with open('result.txt', 'w', encoding='utf-8') as f: f.write(soup.prettify()) ``` - **JavaScript**: 使用`fetch`或`XMLHttpRequest`获取页面内容,...