Я работаю над скребком, работающим на многих страницах, созданных по одному шаблону. Каждая страница содержит некоторую информацию относительно определенного элемента. В оптимистическом случае я хочу получить все доступные данные, для простоты, скажем, это означает имя, цену и описание.
Страницы структурированы следующим образом:
<div id="content">
<h1>Product name</h1>
<table id="properties">
<tbody>
<tr id="manufacturer-row">
<th>Manufacturer</th>
<td>Some-Mark</td>
</tr>
</tbody>
</table>
<p>Full description of the product</p>
</div>
Условия, применимые к этому делу:
- Теги вложены так, что мне нужно проверить наличие каждого уровня,
- На некоторых страницах будут отсутствовать некоторые данные - пустой столбец в таблице такой же возможный, как и отсутствующая таблица,
- На некоторых страницах вообще не будет содержимого,
- Пустой текст в теге является допустимым значением, но пропущенный тег должен быть зарегистрирован,
- Отсутствующие данные не являются исключительной ситуацией.
По сути, я проверяю проверку наличия каждого фрагмента информации, что приводит к довольно трудно читаемому коду:
content = soup.select_one("#content")
if content:
product_name_tag = content.select_one("h1")
if product_name_tag:
name = product_name_tag.text
else:
log("Product name tag not found")
table = content.select_one("table")
if table:
manufacturer_tag = table.select_one("#manufacturer-row > td")
if manufacturer_tag:
manufacturer = manufacturer_tag.text
else:
log("Manufacturer tag not found")
else:
log("Table not found")
else:
log("Tag '#content' not found")
return (
name if name in locals() else None,
manufacturer if manufacturer in locals() else None
)
В реальных приложениях код сложнее читать, так как свойства, которые я ищу, часто бывают более вложенными, и мне нужно проверить существование каждого тега перед извлечением его текста. Мне было интересно, есть ли какой-нибудь аккуратный способ справиться с этой проблемой с точки зрения читабельности кода и краткости? Мои идеи:
Создание функции для извлечения текста тега, если тег существует - сохранит несколько строк, но в реальном приложении я должен использовать регулярные выражения для извлечения некоторых фраз из текста, поэтому одной функции будет недостаточно.
Создание оболочки для записи пропущенных фрагментов, если None был возвращен, а не под кодом «else» - для улучшения читаемости.
Помещение извлечения каждого фрагмента данных в отдельную функцию, как _get_content_if_available, _get_name_if_available
Ни одно из этих решений не кажется достаточно хорошим и лаконичным, поэтому я хотел бы попросить вас об идеях.
Мне также интересно, если мой способ инициализации переменных только при выполнении некоторых условий, а затем проверка наличия переменной в текущем контексте - это хорошая идея.