Я пытаюсь отделить три 3 поля, как в name
, unit
и measure
, из контейнеров с ингредиентами из веб-страница. Я использовал BeautifulSoup для анализа контейнеров с ингредиентами, а затем переделал модуль для разделения unit
и measure
. Это часть этого сайта, с которой я хочу получить три поля.
Вот как я пробовал до сих пор:
import re
import requests
from bs4 import BeautifulSoup
link = 'https://www.delicious.com.au/recipes/gnocchi-walnut-rosemary-pecorino-pesto/1b0defa9-53c8-4e9c-8c93-fb96a5348b31?r=recipes/gallery/opvo6a3l'
def get_content(s,link):
r = s.get(link)
soup = BeautifulSoup(r.text,"lxml")
for item in soup.select("ul.ingredient > li"):
ingr_container = item.get_text(strip=True)
ingr_unit_container = re.search(r"[\d.⁄a-z]+",ingr_container).group(0)
ingr_name = re.sub(ingr_unit_container,"",ingr_container).strip()
ingr_unit = re.sub(r"[a-z]+","",ingr_unit_container).strip()
ingr_measure = re.sub(r"[\d.⁄]+","",ingr_unit_container).strip()
yield ingr_name,ingr_unit,ingr_measure
if __name__ == '__main__':
with requests.Session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
for item in get_content(s,link):
print(item)
Контейнеры для ингредиентов похожи на:
500g potato gnocchi
2 tbs extra virgin olive oil
Finely grated zest and juice of 1 lemon
1⁄2 bunch basil, leaves picked
1 tbs finely chopped rosemary, plus fried rosemary leaves to serve
2 garlic cloves, crushed
50g grated pecorino, (or parmesan) plus extra to serve
50g roasted and chopped walnuts, plus extra to serve
100ml extra virgin olive oil
Текущий вывод, который скрипт производит из указанных выше контейнеров:
('potato gnocchi', '500', 'g')
('tbs extra virgin olive oil', '2', '')
('F grated zest and juice of 1 lemon', '', 'inely')
('bunch basil, leaves picked', '1⁄2', '')
('tbs finely chopped rosemary, plus fried rosemary leaves to serve', '1', '')
('garlic cloves, crushed', '2', '')
('grated pecorino, (or parmesan) plus extra to serve', '50', 'g')
('roasted and chopped walnuts, plus extra to serve', '50', 'g')
('extra virgin olive oil', '100', 'ml')
Ожидаемый результат:
('potato gnocchi', '500', 'g')
('extra virgin olive oil', '2', 'tbs')
('Finely grated zest and juice of', '1', 'lemon')
('basil, leaves picked', '1⁄2', 'bunch')
('finely chopped rosemary, plus fried rosemary leaves to serve', '1', 'tbs')
('cloves, crushed', '2', 'garlic')
('grated pecorino, (or parmesan) plus extra to serve', '50', 'g')
('roasted and chopped walnuts, plus extra to serve', '50', 'g')
('extra virgin olive oil', '100', 'ml')
2 ответа
Я не очень хорошо разбираюсь в регулярных выражениях. Однако я считаю, что работает следующая реализация:
import re
import requests
from bs4 import BeautifulSoup
link = 'https://www.delicious.com.au/recipes/gnocchi-walnut-rosemary-pecorino-pesto/1b0defa9-53c8-4e9c-8c93-fb96a5348b31?r=recipes/gallery/opvo6a3l'
def get_content(s,link):
r = s.get(link)
soup = BeautifulSoup(r.text,"lxml")
for item in soup.select("ul.ingredient > li"):
ingr_container = item.get_text(strip=True)
unit_container = re.search(r'[\d.⁄]+\s*?[a-zA-Z]+\s*?',ingr_container).group(0)
ingr_name = ingr_container.replace(unit_container,"").strip()
ingr_unit = re.search(r'[\d.⁄]+',unit_container).group(0)
ingr_measure = unit_container.replace(ingr_unit,"").strip()
yield ingr_name,ingr_unit,ingr_measure
if __name__ == '__main__':
with requests.Session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
for item in get_content(s,link):
print(item)
Выход:
('potato gnocchi', '500', 'g')
('extra virgin olive oil', '2', 'tbs')
('Finely grated zest and juice of', '1', 'lemon')
('basil, leaves picked', '1⁄2', 'bunch')
('finely chopped rosemary, plus fried rosemary leaves to serve', '1', 'tbs')
('cloves, crushed', '2', 'garlic')
('grated pecorino, (or parmesan) plus extra to serve', '50', 'g')
('roasted and chopped walnuts, plus extra to serve', '50', 'g')
('extra virgin olive oil', '100', 'ml')
Таким образом, одним из решений может быть поиск цифр внутри текста, который является мерой. Это становится немного сложно, потому что иногда единица измерения является частью меры, а иногда между ними есть пустое пространство. Но вы можете догнать это с помощью условий (также может быть решение с регулярным выражением):
import re
import requests
from bs4 import BeautifulSoup
link = 'https://www.delicious.com.au/recipes/gnocchi-walnut-rosemary-pecorino-pesto/1b0defa9-53c8-4e9c-8c93-fb96a5348b31?r=recipes/gallery/opvo6a3l'
def get_content(s,link):
r = s.get(link)
soup = BeautifulSoup(r.text,"lxml")
for item in soup.select("ul.ingredient > li"):
ingr_container = item.get_text(strip=True).split()
for index, string in enumerate(ingr_container):
if re.search(r'\d', string): #check for digits, or parts, that contain digits
if not string.isdecimal(): #check if digits and characters are mixed
if not string.isalnum(): #check if it's a "backslash"-unit (e.g. 1/2)
ingr_measure = string
ingr_unit = ingr_container[index+1]
to_remove = [index, index+1] #at this index (indices) the unit and measure is set
break
else: #split digit and characters
for i, char in enumerate(string):
if char.isalpha():
ingr_measure = string[:i]
ingr_unit = string[i:]
to_remove = [index, index]
break
break
else:
ingr_measure = string
ingr_unit = ingr_container[index+1]
to_remove = [index, index+1]
break
ingr_name = ' '.join(ingr_container[:to_remove[0]] + ingr_container[to_remove[1]+1:]) #ingr_name is the whole ingr_container without measure and unit
yield ingr_name, ingr_measure, ingr_unit
if __name__ == '__main__':
with requests.Session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
for item in get_content(s,link):
print(item)
Выход:
('potato gnocchi', '500', 'g')
('extra virgin olive oil', '2', 'tbs')
('Finely grated zest and juice of', '1', 'lemon')
('basil, leaves picked', '1⁄2', 'bunch')
('finely chopped rosemary, plus fried rosemary leaves to serve', '1', 'tbs')
('cloves, crushed', '2', 'garlic')
('grated pecorino, (or parmesan) plus extra to serve', '50', 'g')
('roasted and chopped walnuts, plus extra to serve', '50', 'g')
('extra virgin olive oil', '100', 'ml')
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.