如何使用ElementTree解析HTML以查找特定的正则表达式?

2 投票
3 回答
16437 浏览
提问于 2025-05-10 09:58

我正在使用 Python 2.7.6 和 ElementTree 来加载和解析一个存储在电脑上的 HTML 文件,然后遍历这个文件,把特定的正则表达式(RegEx)存储到一个数据结构里。

在我的项目文件夹里,有一个名为 person.html 的 HTML 文件:

<!DOCTYPE html>
<html>
    <body>
        <ul>
            <li>Name: $name</li>
            <li>Age: $age</li>
        </ul>
    </body> 
</html>

这是我目前的 Python 脚本(main.py):

#!/usr/bin/env python
import web
import xml.etree.ElementTree as ElementTree

tree = ET.parse(person.html)

我有几个问题:

  1. 我该如何使用正则表达式或 ElementTree 来解析以 $ 开头的值(比如 $name$age)?

  2. 我该如何把这些值存储到一个数据结构中,以便将来可以遍历它们?

相关文章:

  • 暂无相关问题
暂无标签

3 个回答

0

你可以试试用正则表达式(RegEx)这样做:

>>> html = """
... <!DOCTYPE html>
... <html>
...     <body>
...         <ul>
...             <li>Name: $name</li>
...             <li>Age: $age</li>
...         </ul>
...     </body> 
... </html>
... """
>>> import re
>>> re.findall(r'\$\w*', html)
['$name', '$age']
>>> 

re.findall() 这个函数会返回一个列表,所以你可以像这样使用它:

>>> l = re.findall(r'\$\w*', html)
>>> l
['$name', '$age']
>>> l[0]
'$name'
>>> l[1]
'$age'
>>> 
6

lxml 是用来通过标签来搜索 HTML 的工具。比如说,如果你想找到所有的 <li> 标签,并获取它们的文本内容,你可以这样做:

import xml.etree.ElementTree as et

tree = et.parse('data.html')
html_tag = tree.getroot()

for li in html_tag.iter('li'):
    text = li.text
    print(text)

--output:--
Name: $name
Age: $age

如果你想找的文本可能出现在任何标签里,那你可以这样做:

import xml.etree.ElementTree as et
import re

tree = et.parse('data.html')
html_tag = tree.getroot()

pattern = r"""
    \$
    .*?
    \b
"""

for tag in html_tag.iter('*'):  # '*' => all tags
    text = tag.text.strip()

    if text: 
        match_list = re.findall(pattern, text, flags=re.X)
        print (match_list)

--output:--
['$name']
['$age']

我该如何把这些值存储到一个数据结构中,以便将来可以遍历它们呢?

你可以使用 shelve 模块来实现:

$ cat data.html
<!DOCTYPE html>
<html>
    <body>
        <ul>
            <li>Name: $name</li>
            <li>Age: $age</li>
            <li>Dogs: $dog1, $dog2</li>     
        </ul>
    </body> 
</html>

import xml.etree.ElementTree as et
import re
import shelve
import collections as coll

tree = et.parse('data.html')
html_tag = tree.getroot()

pattern = r"""
    \$    #Match a literal $ sign...
    .+?   #followed by any character, 1 or more times, non-greedy
    \b    #followed by the (first) word boundary
"""

results = coll.defaultdict(list)

for tag in html_tag.iter('*'):
    text = tag.text.strip()

    if text: 
        match_list = re.findall(pattern, text, flags=re.X)
        if match_list:
            results['data.html'].extend(match_list)


print(results)

with shelve.open('mydb.db') as db:
    db['html vars'] = results

with shelve.open('mydb.db') as db:
    for key, val in db['html vars'].items():
        print("{}: {}".format(key, val))

--output:--
defaultdict(<class 'list'>, {'data.html': ['$name', '$age', '$dog1', '$dog2']})

data.html: ['$name', '$age', '$dog1', '$dog2']

如果你的最终目标是要在 HTML 中替换这些变量,那么你的格式就适合 Python 的 template 格式:

import string

with open('data.html') as f:
    template = string.Template(f.read())


values = {
    'name': 'socal_javaguy',
    'age': 25,
    'dog1': 'Rover',
    'dog2': 'Jane',
}

results = template.substitute(values)
print(results)

--output:--
<!DOCTYPE html>
<html>
    <body>
        <ul>
            <li>Name: socal_javaguy</li>
            <li>Age: 25</li>
            <li>Dogs: Rover, Jane</li>     
        </ul>
    </body> 
</html>
2

谢谢Kevin和7stud,我已经这样让它工作了:

#!/usr/bin/env python 
import re

with open("person.html", "r") as html_file:
    data=html_file.read()   
list_of_strings = re.findall(r'\$[A-Za-z]+[A-Za-z0-9]*', data)
print list_of_strings

输出结果:

[$name, $age]

撰写回答