Я понимаю, что мой вопрос может показаться не самым удачным, но я действительно изо всех сил пытаюсь разобраться в данной задаче. Я даже обращался к современным ИИ для помощи в создании алгоритма, однако безуспешно. Мне необходимо собрать названия школ и адреса их веб-сайтов. Я сталкиваюсь с двумя типами веб-страниц, которые могут быть следующими: 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) в разных районах, поэтому или просто выводите на экран или записывайте вместе с названием района.