Я понимаю, что мой вопрос может показаться не самым удачным, но я действительно изо всех сил пытаюсь разобраться в данной задаче. Я даже обращался к современным ИИ для помощи в создании алгоритма, однако безуспешно. Мне необходимо собрать названия школ и адреса их веб-сайтов. Я сталкиваюсь с двумя типами веб-страниц, которые могут быть следующими: 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. Настройте задержки между запросами, чтобы не перегружать сервер.
Этот код служит общим шаблоном, и вам, возможно, потребуется адаптировать его в зависимости от структуры конкретного сайта.
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}')
З.Ы. я не знаю могут ли быть одинаковые наименования (например МБДОУ ДС №5) в разных районах, поэтому или просто выводите на экран или записывайте вместе с названием района.