我需要在丑陋的HTML文件的文本中找到模式。它很难看,因为每个角色都包含在一个绝对定位的<span>
中,每个<span>
都在它自己的行上,如下所示:
<span style="position:absolute; color:black; left:422px; top:3497px; font-size:21.6px;">M</span>
<span style="position:absolute; color:black; left:440px; top:3497px; font-size:21.6px;">T</span>
<span style="position:absolute; color:black; left:452px; top:3497px; font-size:21.6px;">V</span>
<span style="position:absolute; color:black; left:464px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:470px; top:3497px; font-size:21.6px;">N</span>
<span style="position:absolute; color:black; left:484px; top:3497px; font-size:21.6px;">e</span>
<span style="position:absolute; color:black; left:493px; top:3497px; font-size:21.6px;">t</span>
<span style="position:absolute; color:black; left:499px; top:3497px; font-size:21.6px;">w</span>
<span style="position:absolute; color:black; left:513px; top:3497px; font-size:21.6px;">o</span>
<span style="position:absolute; color:black; left:523px; top:3497px; font-size:21.6px;">r</span>
<span style="position:absolute; color:black; left:531px; top:3497px; font-size:21.6px;">k</span>
<span style="position:absolute; color:black; left:541px; top:3497px; font-size:21.6px;">s</span>
<span style="position:absolute; color:black; left:549px; top:3497px; font-size:21.6px;">,</span>
<span style="position:absolute; color:black; left:554px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:559px; top:3497px; font-size:21.6px;">I</span>
<span style="position:absolute; color:black; left:566px; top:3497px; font-size:21.6px;">n</span>
<span style="position:absolute; color:black; left:577px; top:3497px; font-size:21.6px;">c</span>
<span style="position:absolute; color:black; left:586px; top:3497px; font-size:21.6px;">.</span>
<span style="position:absolute; color:black; left:592px; top:3497px; font-size:21.6px;">,</span>
<span style="position:absolute; color:black; left:597px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:602px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:613px; top:3497px; font-size:21.6px;">5</span>
<span style="position:absolute; color:black; left:623px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:634px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:639px; top:3497px; font-size:21.6px;">F</span>
<span style="position:absolute; color:black; left:650px; top:3497px; font-size:21.6px;">.</span>
<span style="position:absolute; color:black; left:656px; top:3497px; font-size:21.6px;">3</span>
<span style="position:absolute; color:black; left:666px; top:3497px; font-size:21.6px;">d</span>
<span style="position:absolute; color:black; left:677px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:682px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:693px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:703px; top:3497px; font-size:21.6px;">0</span>
<span style="position:absolute; color:black; left:714px; top:3497px; font-size:21.6px;">9</span>
<span style="position:absolute; color:black; left:724px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:729px; top:3497px; font-size:21.6px;">(</span>
<span style="position:absolute; color:black; left:736px; top:3497px; font-size:21.6px;">9</span>
<span style="position:absolute; color:black; left:747px; top:3496px; font-size:13.6px;">t</span>
<span style="position:absolute; color:black; left:751px; top:3496px; font-size:13.6px;">h</span>
<span style="position:absolute; color:black; left:757px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:763px; top:3497px; font-size:21.6px;">C</span>
<span style="position:absolute; color:black; left:777px; top:3497px; font-size:21.6px;">i</span>
<span style="position:absolute; color:black; left:782px; top:3497px; font-size:21.6px;">r</span>
<span style="position:absolute; color:black; left:789px; top:3497px; font-size:21.6px;">.</span>
<span style="position:absolute; color:black; left:795px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:800px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:810px; top:3497px; font-size:21.6px;">9</span>
<span style="position:absolute; color:black; left:821px; top:3497px; font-size:21.6px;">9</span>
<span style="position:absolute; color:black; left:831px; top:3497px; font-size:21.6px;">8</span>
<span style="position:absolute; color:black; left:842px; top:3497px; font-size:21.6px;">)</span>
这是我想要匹配的正则表达式(在Vim语法中):[0-9]\+ F\.3d [0-9]\+
。因此,在此示例中,我想匹配152 F.3d 1209
。我希望将其包含在<a>
中以最终结果:
<a href="http://www.stackoverflow.com/">
<span style="position:absolute; color:black; left:602px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:613px; top:3497px; font-size:21.6px;">5</span>
<span style="position:absolute; color:black; left:623px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:634px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:639px; top:3497px; font-size:21.6px;">F</span>
<span style="position:absolute; color:black; left:650px; top:3497px; font-size:21.6px;">.</span>
<span style="position:absolute; color:black; left:656px; top:3497px; font-size:21.6px;">3</span>
<span style="position:absolute; color:black; left:666px; top:3497px; font-size:21.6px;">d</span>
<span style="position:absolute; color:black; left:677px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:682px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:693px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:703px; top:3497px; font-size:21.6px;">0</span>
<span style="position:absolute; color:black; left:714px; top:3497px; font-size:21.6px;">9</span>
</a>
我可以编写一个详细的正则表达式来忽略每个HTML标记,但很快就会变得不可行(例如,如果每个数字前后都有HTML标记,则很难匹配[0-9]\+
。
我可以使用类似%s/<.*>\(.*\)<.*>/\1/g
的内容删除HTML,但这也不起作用,因为我需要保留格式。
我得到了can't parse HTML with a regex。但我不需要解析任意HTML;我只需要解决一组已知的标签。有一种优雅的方式来做到这一点?或者我应该放弃正则表达式并使用类似XPath解析器的东西吗?
我对任何语言都很开放,但我更喜欢使用Python,JavaScript或Vim。
答案 0 :(得分:2)
好吧,我会将文本节点提取到一个简单的字符串,匹配它,然后返回到DOM树来检索初始HTML。这样的事情:
import lxml.html, lxml.etree
import re
with open('foo.html') as f:
source = lxml.html.parse(f)
letters = source.findall('//span')
string = ''.join(s.text for s in letters)
match = re.search(r'[0-9]+ F\.3d [0-9]+', string)
assert match is not None
start, end = match.span()
html = '\n'.join(lxml.etree.tostring(el).decode('utf8')
for el in letters[start:end])
print('<a href="foo">{}</a>'.format(html))
请注意,循环中的tostring()
可能不是性能最好的。您应该构建a
元素,在其中附加字母并在tostring()
元素上调用a
一次。
答案 1 :(得分:2)
此代码缺少大量错误处理,并且依赖于严格的输入格式,但请考虑:
import re
import os
html = '''<span style="position:absolute; color:black; left:422px; top:3497px; font-size:21.6px;">M</span>
<span style="position:absolute; color:black; left:440px; top:3497px; font-size:21.6px;">T</span>
<span style="position:absolute; color:black; left:452px; top:3497px; font-size:21.6px;">V</span>
... (Lines omitted)
<span style="position:absolute; color:black; left:842px; top:3497px; font-size:21.6px;">)</span>
'''
# This is sloppy, but if your input format remains the same should work...
chars = ''.join([line[line.find('>') + 1] for line in html.splitlines()])
# chars => "MTV Networks, Inc., 152 F.3d 1209 (9th Cir. 1998)"
# Use regex to search chars
mat = re.search(r'\d+ F\.3d \d+', chars)
# Extract lines from html based on the start and end positions of the regex match
block = html.splitlines()[mat.start():mat.end()]
# Wrap the lines with your anchor tag
block = ['<a href="http://www.stackoverflow.com/>'] + block + ['</a>']
# Print the list
print os.linesep.join(block)
它首先提取<span>
标记内的单个字符并将它们放在一个字符串中。然后它搜索该字符串以获取正则表达式(针对python的re
模块进行了修改)。
由于chars
字符串中字符的位置与html
中相应行的行号完全对应,我们可以使用{{1}内匹配的开始和结束位置}} string选择我们想要换行的chars
行。
我们在开始和结束时将元素插入到html
列表中,对应于您的锚标记,并将其打印出来。
只要您的输入完全符合您的指定,就不需要调用DOM解析器或任何非常复杂的东西 - 尽管可能需要类似的东西。
答案 2 :(得分:1)
这是使用awk的解决方案:
$ cat mornin.awk
NR == FNR {
gsub("</?span[^<]*>","",$0)
s = s $0
next
}
FNR == 1 {
i = match(s, "[0-9]+ F\.3d [0-9]+")
len = RLENGTH
print "<a href=\"http://www.stackoverflow.com/\">"
}
FNR == i, FNR == (i + RLENGTH - 1)
END {
print "</a>"
}
此解决方案需要对文本进行两次传递,因此您将文件放在命令行上两次:
$ awk -f mornin.awk mornin.txt mornin.txt
<a href="http://www.stackoverflow.com/">
<span style="position:absolute; color:black; left:602px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:613px; top:3497px; font-size:21.6px;">5</span>
<span style="position:absolute; color:black; left:623px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:634px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:639px; top:3497px; font-size:21.6px;">F</span>
<span style="position:absolute; color:black; left:650px; top:3497px; font-size:21.6px;">.</span>
<span style="position:absolute; color:black; left:656px; top:3497px; font-size:21.6px;">3</span>
<span style="position:absolute; color:black; left:666px; top:3497px; font-size:21.6px;">d</span>
<span style="position:absolute; color:black; left:677px; top:3497px; font-size:21.6px;"> </span>
<span style="position:absolute; color:black; left:682px; top:3497px; font-size:21.6px;">1</span>
<span style="position:absolute; color:black; left:693px; top:3497px; font-size:21.6px;">2</span>
<span style="position:absolute; color:black; left:703px; top:3497px; font-size:21.6px;">0</span>
<span style="position:absolute; color:black; left:714px; top:3497px; font-size:21.6px;">9</span>
</a>