Да, для каждого сайта должен быть написан специальный шаблон регулярных выражений.
Но я думаю, что
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))
.
EDIT
Я скачал и установил 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 я учел замечания Ахима в другой ветке сообщений: используя 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 не влияет на скорость для простого регулярного выражения.
Регулярное выражение с флагами, без x и y, выполняется дольше, но результат не совпадает с другими, потому что он захватывает дополнительный фрагмент текста. Вот почему в реальном приложении следует использовать регулярное выражение с флагами и x / y.
Более сложное регулярное выражение с флагами и с x и y занимает на 20% меньше времени.
Ну, результаты не очень сильно изменились, с х / у или без него.
Так что мой вывод тот же
использование регулярного выражения, прибегая к
find () или нет, остается примерно в 1000 раз быстрее, чем BeautifulSoup,
и я оцениваю в 100 раз быстрее чем
lxml (я не установил lxml)
.
На то, что вы написали, Хью, я бы сказал:
Когда регулярное выражение неверно, оно не быстрее и не медленнее. Это не работает.
Когда регулярное выражение неверно, кодер делает его правильным, вот и все.
Я не понимаю, почему 95% людей на stackoverflow.com хотят убедить другие 5%, что регулярные выражения не должны использоваться для анализа HTML, XML или чего-либо еще. Я говорю «анализировать», а не «анализировать». Насколько я понял, парсер сначала анализирует ВЕСЬ текста, а затем отображает содержание элементов, которые мы хотим. Напротив, регулярное выражение подходит к тому, что ищется, оно не строит дерево текста HTML / XML или что-то еще, что делает парсер, и что я не очень хорошо знаю.
Итак, я очень доволен регулярными выражениями. У меня нет проблем с написанием даже очень длинных RE, и регулярные выражения позволяют мне запускать программы, которые должны быстро реагировать после анализа текста. BS или lxml будут работать, но это будет хлопотно.
У меня были бы другие комментарии, но у меня нет времени на предмет, по которому я фактически позволяю другим делать то, что они предпочитают.