Здравствуйте! У меня есть код для парсинга данных с сайта <a href="https://etender.gov.az/" rel="nofollow">https://etender.gov.az/</a>. Можете помочь мне разобраться с его работой? Вот сам код: <br/> <pre><code class="python">import requests import pandas as pd from concurrent.futures import ThreadPoolExecutor, as_completed import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException main_data = { 'Organization_name': [], 'Organization_voen': [], 'Organization_address': [], 'Event_name': [], 'Event_number': [], 'Classification_code': [], 'Suggested_price': [], 'Event_start_date': [], 'Submission_deadline': [], 'Envelope_opening_date': [], 'Participation_fee': [], 'Participation_description': [], 'Usage_fee': [], 'Usage_description': [], 'Full_name': [], 'Contact': [], 'Position': [], 'Phone_number': [] } nested_data = { 'Heading': [], 'Disclosure': [], 'Quantity': [], 'Measure_unit': [], 'Code': [] } def get_total_items_from_link(api_link='https://etender.gov.az/api/events?EventType=2&PageSize=1&PageNumber=1&EventStatus=1&Keyword=&buyerOrganizationName=&PrivateRfxId=&publishDateFrom=&publishDateTo=&AwardedparticipantName=&AwardedparticipantVoen=&DocumentViewType='): try: response = requests.get(api_link, timeout=20) if response.status_code == 200: data = response.json() return data['totalItems'] except requests.Timeout
Ваш код для парсинга данных с сайта имеет некоторые области, где можно повысить эффективность и улучшить его структуру. Рассмотрим несколько способов оптимизации: ### 1. Использование асинхронного выполнения Если вы работаете с большим количеством запросов, можно рассмотреть использование `asyncio` и `aiohttp`, чтобы улучшить производительность путем выполнения нескольких запросов параллельно, не блокируя основной поток. ### 2. Улучшение обработки исключений Текущая обработка исключений не завершает выполнение функции, если возникает ошибка. Можно добавить больше информации об исключении и, возможно, повторить попытку загрузки данных. ### 3. Избегание глобальных переменных Попробуйте минимизировать использование глобальных переменных, чтобы улучшить читабельность кода и избежать потенциальных ошибок. ### 4. Использование `with` для работы с Selenium Управление ресурсами WebDriver через конструкцию `with` гарантирует, что браузер будет правильно закрыт, даже если произойдет ошибка. ### 5. Снижение количества запросов Проверьте, можно ли получить больше данных за один запрос (если API это позволяет), чтобы уменьшить общее количество запросов. ### Пример оптимизированного кода Пример исправленного кода с применением некоторых упомянутых оптимизаций: ```python import requests import pandas as pd from concurrent.futures import ThreadPoolExecutor import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, TimeoutException class TenderParser: def __init__(self): self.main_data = self.initialize_data_structure() self.nested_data = self.initialize_data_structure() def initialize_data_structure(self): return { 'Organization_name': [], 'Organization_voen': [], 'Organization_address': [], # Другие поля... } def get_total_items_from_link(self, api_link): try: response = requests.get(api_link, timeout=20) response.raise_for_status() # Проверка на ошибки HTTP data = response.json() return data.get('totalItems', 0) except (requests.Timeout, requests.RequestException) as e: print(f"Ошибка получения данных: {e}") return 0 def parse_data(self, detail_link): with webdriver.Chrome() as driver: # Используем with для управления ресурсами driver.get(detail_link) # Ваша логика парсинга... def run(self, api_link): total_items = self.get_total_items_from_link(api_link) with ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(self.parse_data, detail_link): detail_link for detail_link in self.get_detail_links(total_items)} for future in as_completed(futures): try: future.result() # Получаем результат, если нужно except Exception as e: print(f"Ошибка при обработке: {e}") def get_detail_links(self, total_items): # Логика для получения полных ссылок на детали тендеров pass if __name__ == "__main__": parser = TenderParser() parser.run('https://etender.gov.az/api/events?EventType=2&PageSize=1&PageNumber=1&EventStatus=1&Keyword=') ``` ### Заключение Эти оптимизации не только улучшат производительность и надежность вашего кода, но также повысят его читабельность и облегчите дальнейшее сопровождение.
Все не смотрел, но простыни типа:
def get_contact(ids): for id in ids: template = f'https://etender.gov.az/api/events/{id}/contact-persons' try: response = requests.get(template, timeout=20) if response.status_code == 200: data_list = response.json() for data in data_list: main_data['Full_name'].append(data.get('fullName', 'None') if data.get('fullName') else 'None') main_data['Contact'].append(data.get('contact', 'None') if data.get('contact') else 'None') main_data['Position'].append(data.get('position', 'None') if data.get('position') else 'None') main_data['Phone_number'].append(data.get('phoneNumber', 'None') if data.get('phoneNumber') else 'None') else: main_data['Full_name'].append('None') main_data['Contact'].append('None') main_data['Position'].append('None') main_data['Phone_number'].append('None') except requests.Timeout: main_data['Full_name'].append('None') main_data['Contact'].append('None') main_data['Position'].append('None') main_data['Phone_number'].append('None')
пишутся гораздо проще. Да и структуру данных я бы поправил. К примеру простыня выше заменяется более лаконичным кодом:
main_data = [] ... def get_contact(ids): for id in ids: current_data = {} template = f'https://etender.gov.az/api/events/{id}/contact-persons' try: response = requests.get(template, timeout=20) if response.status_code == 200: data_list = response.json() for (elem_to, elem_from) in [ ('Full_name', 'fullName'), ('Contact', 'contact'), ('Position', 'position'), ('Phone_number', 'phoneNumber') ]: current_data[elem_to] = data.get(elem_from, 'None') except requests.Timeout: pass main_data.apend()