Python Regex Scrape & Replace String



嗨,我想为我编写一个小助手 Python 工具,它应该处理以下内容:

<tr>
<td><p>L1</p></td>
<td><p>(4.000x2.300x500;   4,6m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.221 kg</p></td>
</tr>
<tr>
<td><p>L2</p></td>
<td><p>(4.250x2.300x500;   4,9m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.279 kg</p></td>
</tr>
<tr>
<td><p>L3</p></td>
<td><p>(4.500x2.300x500;   5,2m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.321 kg</p></td>
</tr>
<tr>
<td><p>L4</p></td>
<td><p>(4.750x2.300x500;   5,5m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.364 kg</p></td>
</tr>

它应该将每个表行的&nbsp;替换为每行第二个表数据字段中的 ; 和 ( 之间的卷。

我开始像这样用 Python 编写代码,我可以使用正则表达式语句抓取卷,但我的逻辑结束于如何将值放在正确的位置。 任何想法 ? 这是我的代码

import BeautifulSoup
import re
with open('3mmcontainer.html') as f:
content = f.read()
f.close()
#print content
contentsoup = BeautifulSoup.BeautifulSoup(content)
for tablerow in contentsoup.findAll('tr'):
inhalt = str(tablerow.contents[3])
print inhalt

match = re.findall(';(.*?))', inhalt)

print match
# for x in match:
#    volumen = x.lstrip()
#    print volumen
#f = open('3mmcontainer.html', 'w')
#newdata = f.replace("&nbsp;", volumen)
#f.write(newdata)
#f.close()

#m = re.search(';(.*?))', inhalt)
# print m
# volumen = re.compile(r';(.*?))')
# volumen.match(tablerow.contents[3])

注意:你不需要调用close(),因为with语句会为你做这件事。

您可以使用简单的函数来转换每一行(<tr/>(:

import re

def parse_inhalt(content):
td_list = re.findall(r"<td>(?:(?!</td>).)+</td>", content)
vol_content = td_list[1]
vol = re.findall(r";([^)]+)", vol_content)[0]
return content.replace("&nbsp;", vol)

代码很简单:

  • 提取td_list中的每个细胞
  • 获取包含卷的第二个单元格的内容
  • 查找包含在";"和"("之间的(不包括这些字符(
  • &nbsp;替换为

例如:

inhalt = u"""
<tr>
<td><p>L4</p></td>
<td><p>(4.750x2.300x500;   5,5m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.364 kg</p></td>
</tr>"""
print(parse_inhalt(inhalt))

你会得到:

<tr>
<td><p>L4</p></td>
<td><p>(4.750x2.300x500;   5,5m³)</p></td>
<td><p>   5,5m³</p></td>
<td><p> 1.364 kg</p></td>
</tr>

您可以使用以下命令删除空格:

vol = re.findall(r";s*([^)]+)", vol_content)[0]

另一种方法。

首先,查找所有表格单元格以及其中的p元素。您知道p元素的特征是在其text中存在,因此请注意它们,并且您知道必须立即更改p元素。然后安排在遇到该区域时捕获该区域,记下p元素的序号,然后在遇到下一个p元素时,通过将area分配给其string属性来更改其text

如果你更喜欢正则表达式,那么你可以使用它来计算area

area = bs4.re.search(r';s+([^)]+)', p.text).groups(0)[0]

.

>>> import bs4
>>> soup = bs4.BeautifulSoup(open('temp.htm').read(), 'lxml')
>>> k = None
>>> for i, p in enumerate(soup.select('td > p')):
...     if 'm³' in p.text:
...         area = p.text[1+p.text.rfind(';'):-1].strip()
...         k = i
...     if k and i == k + 1:
...         p.string = area
... 
>>> soup
<html><body><tr>
<td><p>L1</p></td>
<td><p>(4.000x2.300x500;   4,6m³)</p></td>
<td><p>4,6m³</p></td>
<td><p> 1.221 kg</p></td>
</tr>
<tr>
<td><p>L2</p></td>
<td><p>(4.250x2.300x500;   4,9m³)</p></td>
<td><p>4,9m³</p></td>
<td><p> 1.279 kg</p></td>
</tr>
<tr>
<td><p>L3</p></td>
<td><p>(4.500x2.300x500;   5,2m³)</p></td>
<td><p>5,2m³</p></td>
<td><p> 1.321 kg</p></td>
</tr>
<tr>
<td><p>L4</p></td>
<td><p>(4.750x2.300x500;   5,5m³)</p></td>
<td><p>5,5m³</p></td>
<td><p> 1.364 kg</p></td>
</tr></body></html>
>>> 

如果暴力正则表达式可以接受

s='''
<tr>
<td><p>L1</p></td>
<td><p>(4.000x2.300x500;   4,6m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.221 kg</p></td>
</tr>
<tr>
<td><p>L2</p></td>
<td><p>(4.250x2.300x500;   4,9m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.279 kg</p></td>
</tr>
<tr>
<td><p>L3</p></td>
<td><p>(4.500x2.300x500;   5,2m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.321 kg</p></td>
</tr>
<tr>
<td><p>L4</p></td>
<td><p>(4.750x2.300x500;   5,5m³)</p></td>
<td><p>&nbsp;</p></td>
<td><p> 1.364 kg</p></td>
</tr>
'''
import re
p=r'(([0-9x.]+)(; +)([0-9,m³]+)()</p></td>n <td><p>)(&nbsp;)'
# not sure which output is preferred
x = re.sub(p, 'g<1>g<2>g<3>g<4>g<3>', s)
print(x)
y = re.sub(p, 'g<1>g<4>g<3>', s)
print(y)

最新更新