Я понимаю, что мой вопрос может показаться не самым удачным, но я действительно изо всех сил пытаюсь разобраться в данной задаче. Я даже обращался к современным ИИ для помощи в создании алгоритма, однако безуспешно. Мне необходимо собрать названия школ и адреса их веб-сайтов. Я сталкиваюсь с двумя типами веб-страниц, которые могут быть следующими: 1. Страницы, содержащие списки городов или районов 2. Страницы с адресами школ в конкретном городе или районе Проще говоря, адрес к нужной странице может выглядеть как: Уфа->Дема->*Адреса школ или как: Янаул->*Адреса школ. Таким образом, иерархия всегда произвольная, но адреса школ всегда находятся на конечном уровне. На страницах со списками городов/районов/республик я ищу все теги *a внутри тега *div, а на страницах с адресами школ обращаю внимание на теги *a в таблице. Теперь я не знаю, как реализовать это рекурсивно, избегая множества вложенных циклов. Есть ли у кого-либо идеи по этому поводу?
Ваше задание по извлечению данных с веб-сайтов можно решить с помощью веб-скрейпинга, который включает в себя рекурсивное обход всех необходимых страниц. Для реализации вашей задачи в Python можно использовать библиотеки `requests` и `BeautifulSoup`. Примерный алгоритм может выглядеть следующим образом:
1. Начинаем с основной страницы, содержащей списки городов/районов.
2. Извлекаем ссылоки на города/районы и рекурсивно переходим к ним.
3. Повторяем шаг 2 до тех пор, пока не достигнем страницы, содержащей адреса школ.
4. На странице с адресами школ извлекаем название и ссылки на веб-сайты школ.
Вот пример кода, который демонстрирует этот процесс:
```python
import requests
from bs4 import BeautifulSoup
def scrape_school_links(url, visited=None):
if visited is None:
visited = set() # Для отслеживания посещенных страниц
if url in visited:
return
visited.add(url)
try:
response = requests.get(url)
response.raise_for_status() # Проверка ошибок HTTP
except requests.RequestException as e:
print(f"Ошибка получения {url}: {e}")
return
soup = BeautifulSoup(response.text, 'html.parser')
# Проверяем на наличие ссылок на школы
school_links = []
table = soup.find('table') # Предполагаем, что адреса школ в таблице
if table:
for row in table.find_all('tr'):
# Извлекаем название школы и ссылку на сайт
columns = row.find_all('td')
if len(columns) > 1:
school_name = columns[0].get_text(strip=True)
school_url = columns[1].find('a')['href'] if columns[1].find('a') else None
if school_url:
school_links.append((school_name, school_url))
print(f"Найдены школы на {url}: {school_links}")
# Проверяем наличие ссылок на города/районы
divs = soup.find_all('div') # Предполагаем, что ссылки на города/районы внутри div
for div in divs:
for a in div.find_all('a', href=True):
next_url = a['href']
if next_url.startswith('/'): # Относительный путь
next_url = f"{url}/{next_url}"
scrape_school_links(next_url, visited) # Рекурсивный вызов
# Пример начального URL
start_url = "http://example.com/cities" # Замените на реальный URL
scrape_school_links(start_url)
```
### Пояснения к коду:
- **requests.get** используется для получения HTML-кода страницы.
- **BeautifulSoup** позволяет парсить HTML и извлекать данные.
- В **scrape_school_links** реализован рекурсивный обход, который сначала собирает ссылки на школы, а затем ищет города/районы.
- Использование **set()** для хранения уже посещённых URL позволяет избежать бесконечных циклов.
### Важно:
1. Убедитесь, что у вас есть разрешение на скрейпинг данных с сайта.
2. Обратите внимание на правила `robots.txt` сайта, который вы собираетесь скрейпить.
3. Настройте задержки между запросами, чтобы не перегружать сервер.
Этот код служит общим шаблоном, и вам, возможно, потребуется адаптировать его в зависимости от структуры конкретного сайта.
<pre><code class="python">import requests
from bs4 import BeautifulSoup
def parse_table(div, results):
# Ищем таблицы внутри данного div
tables = div.find_all('table')
for table in tables:
rows = table.find_all('tr')
for row in rows:
cells = row.find_all('td')
if cells:
# Извлекаем название и ссылку
name = cells[0].get_text(strip=True)
link = cells[0].find('a')['href'] if cells[0].find('a') else None
if link:
results[name] = link
def recursive_parse(url, visited, results):
if url in visited:
return
visited.add(url)
print('Парсим URL:', url)
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# Ищем все div с itemscope
divs = soup.find_all('div', itemscope=True)
for div in divs:
parse_table(div, results) # Парсим таблицы внутри найденного div
# Ищем все ссылки на подстраницы
links = soup.find_all('a', href=True)
for link in links:
sub_url = link['href']
# Проверяем, что ссылка ведет на подстраницу и не является текущим URL
if 'respublika_bashkortostan' in sub_url and sub_url.startswith('http') and sub_url != url:
recursive_parse(sub_url, visited, results)
# Начальная URL
start_url = 'https://russiaschools.ru/respublika_bashkortostan/'
visited_urls = set()
results_dict = {}
recursive_parse(start_url, visited_urls, results_dict)
for name, link in results_dict.items():
print(f'Название: {name}, Ссылка: {link}')</code></pre> <br/> <br/> З.Ы. я не знаю могут ли быть одинаковые наименования (например МБДОУ ДС №5) в разных районах, поэтому или просто выводите на экран или записывайте вместе с названием района.