是的,必须为每个站点编写一个特殊的正则表达式模式。
但我认为
1- 使用 Beautiful Soup 进行的处理也必须适应每个站点。
2-正则表达式写起来没那么复杂,稍有习惯就可以很快搞定
我很好奇必须对 Beautiful Soup 进行什么样的处理才能获得与我在几分钟内获得的相同结果。曾几何时,我试图学习美丽的汤,但我对这个烂摊子没有任何理解。我应该再试一次,现在我对 Python 更熟练了。但是到目前为止,正则表达式对我来说还可以,也足够了
这是这个新网站的代码:
import urllib
import re
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
sock = urllib.urlopen(url)
ch = sock.read()
sock.close()
x = ch.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
print '\n'.join(patingr.findall(ch,x))
.
编辑
我下载并安装了 BeautifulSoup 并与正则表达式进行了比较。
我认为我的比较代码没有任何错误
import urllib
import re
from time import clock
import BeautifulSoup
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
data = urllib.urlopen(url).read()
te = clock()
x = data.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res1 = '\n'.join(patingr.findall(data,x))
t1 = clock()-te
te = clock()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
ingreds = [s.getText().strip() for s in ingreds.findAll('li')]
res2 = '\n'.join(ingreds)
t2 = clock()-te
print res1
print
print res2
print
print 'res1==res2 is ',res1==res2
print '\nRegex :',t1
print '\nBeautifulSoup :',t2
print '\nBeautifulSoup execution time / Regex execution time ==',t2/t1
结果
1/4 cup olive oil
1 cup chicken broth
2 cloves garlic, minced
1 tablespoon paprika
1 tablespoon garlic powder
1 tablespoon poultry seasoning
1 teaspoon dried oregano
1 teaspoon dried basil
4 thick cut boneless pork chops
salt and pepper to taste
1/4 cup olive oil
1 cup chicken broth
2 cloves garlic, minced
1 tablespoon paprika
1 tablespoon garlic powder
1 tablespoon poultry seasoning
1 teaspoon dried oregano
1 teaspoon dried basil
4 thick cut boneless pork chops
salt and pepper to taste
res1==res2 is True
Regex : 0.00210892725193
BeautifulSoup : 2.32453566026
BeautifulSoup execution time / Regex execution time == 1102.23605776
没有评论!
.
编辑 2
我意识到在我的代码中我不使用正则表达式,我采用了一个使用正则表达式和 find() 的方法。
这是我使用正则表达式时使用的方法,因为它在某些情况下会提高处理速度。这是由于函数 find() 运行得非常快。
要知道我们在比较什么,我们需要以下代码。
在代码 3 和 4 中,我考虑了 Achim 在另一个帖子中的评论:使用 re.IGNORECASE 和 re.DOTALL,["\'] 而不是 " 。
这些代码是分开的,因为它们必须在不同的文件中执行才能获得可靠的结果:我不知道为什么,但是如果所有代码都在同一个文件中执行,某些结果时间是非常不同的(0.00075例如,而不是 0.0022)
import urllib
import re
import BeautifulSoup
from time import clock
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
data = urllib.urlopen(url).read()
# Simple regex , without x
te = clock()
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res0 = '\n'.join(patingr.findall(data))
t0 = clock()-te
print '\nSimple regex , without x :',t0
和
# Simple regex , with x
te = clock()
x = data.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res1 = '\n'.join(patingr.findall(data,x))
t1 = clock()-te
print '\nSimple regex , with x :',t1
和
# Regex with flags , without x and y
te = clock()
patingr = re.compile('<li class=["\']plaincharacterwrap["\']>\r\n +(.+?)</li>\r\n',
flags=re.DOTALL|re.IGNORECASE)
res10 = '\n'.join(patingr.findall(data))
t10 = clock()-te
print '\nRegex with flags , without x and y :',t10
和
# Regex with flags , with x and y
te = clock()
x = data.find('Ingredients</h3>')
y = data.find('h3>\r\n Footnotes</h3>\r\n')
patingr = re.compile('<li class=["\']plaincharacterwrap["\']>\r\n +(.+?)</li>\r\n',
flags=re.DOTALL|re.IGNORECASE)
res11 = '\n'.join(patingr.findall(data,x,y))
t11 = clock()-te
print '\nRegex with flags , without x and y :',t11
和
# BeautifulSoup
te = clock()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
ingreds = [s.getText().strip() for s in ingreds.findAll('li')]
res2 = '\n'.join(ingreds)
t2 = clock()-te
print '\nBeautifulSoup :',t2
结果
Simple regex , without x : 0.00230488284125
Simple regex , with x : 0.00229121279385
Regex with flags , without x and y : 0.00758719458758
Regex with flags , with x and y : 0.00183724493364
BeautifulSoup : 2.58728860791
使用 x 对简单正则表达式的速度没有影响。
带有 flags 的正则表达式,没有 x 和 y,需要更长的时间来执行,但结果与其他的不一样,因为它捕获了一个补充文本块。这就是为什么在实际应用程序中,应该使用带有标志和 x/y 的正则表达式。
带有标志和 x 和 y 的更复杂的正则表达式减少 20% 的时间。
嗯,无论有没有 x/y,结果都没有太大变化。
所以我的结论是一样的
使用正则表达式,诉诸于
find() 与否,仍然比 BeautifulSoup 快大约 1000 倍,
我估计要快 100 倍
lxml(我没有安装lxml)
.
对于你写的,休,我想说:
当一个正则表达式错误时,它既不快也不慢。它没有运行。
当一个正则表达式出错时,编码器会使其变得正确,仅此而已。
我不明白为什么 stackoverflow.com 上 95% 的人想要说服其他 5% 的人不要使用正则表达式来分析 HTML 或 XML 或其他任何内容。我说“分析”,而不是“解析”。据我了解,解析器首先分析整个文本,然后显示我们想要的元素的内容。相反,正则表达式直接用于搜索的内容,它不会构建 HTML/XML 文本树或解析器所做的任何其他事情,我不太了解。
所以,我对正则表达式非常满意。我可以编写很长的 RE,而且正则表达式允许我运行在分析文本后必须迅速做出反应的程序。 BS 或 lxml 可以,但那会很麻烦。
我还有其他的 cmets 要做,但我没有时间做一个主题,事实上,我让其他人随心所欲地做。