import docx import csv import re def extract_quoted_text(text): """Извлекает текст в кавычках «»""" if not text: return "" match = re.search(r'«([^»]+)»', text) return match.group(1).strip() if match else text.strip() def extract_address(text): """Извлекает адрес, содержащий г. или Г.""" if not text: return "" # Ищем текст с "г." или "Г." if re.search(r'[гГ]\.', text): return text.strip() return "" def extract_email(text): """Извлекает email из текста и убирает пробелы после @""" if not text: return "" # Убираем пробелы после @ text = re.sub(r'@\s+', '@', text) # Ищем паттерн email email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' match = re.search(email_pattern, text) return match.group(0) if match else "" def extract_phone(text): """Извлекает телефон из текста""" if not text: return "" # Убираем лишние пробелы return text.strip() def parse_contact_data(cells): """Парсит данные контакта из ячеек таблицы""" # Объединяем весь текст из всех ячеек для анализа all_text = ' '.join(cells) # ВАЖНО: Парсим только строки с email! has_email = '@' in all_text if not has_email: return None contact = { 'Имя': '', 'Фамилия': '', 'Отчество': '', 'Организация': '', 'Телефон': '', 'E-mail': '' } # Ищем email for cell in cells: email = extract_email(cell) if email: contact['E-mail'] = email break # Ищем организацию/имя в кавычках «» organization_found = False for cell in cells: quoted_match = re.search(r'«([^»]+)»', cell) if quoted_match: contact['Организация'] = quoted_match.group(1).strip() organization_found = True break # Если не нашли в кавычках, ищем название ЗАГЛАВНЫМИ буквами if not organization_found: for cell in cells: # Ищем текст заглавными буквами (название организации обычно так) # Исключаем строки с email и телефонами if cell and not '@' in cell and not re.search(r'8\s*\(\d+\)', cell): # Проверяем, есть ли заглавные слова upper_words = re.findall(r'[А-ЯЁA-Z][А-ЯЁA-Z\s\-\.]+', cell) if upper_words: # Берем самое длинное совпадение longest = max(upper_words, key=len).strip() if len(longest) > 10: # Минимум 10 символов для названия contact['Организация'] = longest organization_found = True break # Ищем адрес (содержит г. или Г.) и добавляем к организации for cell in cells: address_match = re.search(r'\d{6},\s*[гГ]\.\s*[^,]+(?:,\s*[^,]+)*', cell) if address_match: address = address_match.group(0) if contact['Организация'] and address not in contact['Организация']: contact['Организация'] += ', ' + address elif not contact['Организация']: contact['Организация'] = address break # Ищем телефон (только основной, если есть) for cell in cells: # Ищем паттерн телефона phone_match = re.search(r'8\s*\(\d+\)\s*[\d\-]+', cell) if phone_match: contact['Телефон'] = phone_match.group(0).strip() break return contact def parse_phone_book(): """Парсит телефонную книгу из Word документа и сохраняет в CSV""" # Открываем документ doc = docx.Document('./04_Телефонный справочник_МАКСИМ.docx') # Список для хранения контактов contacts = [] # Обрабатываем каждую таблицу в документе for table in doc.tables: # Пропускаем первую строку (заголовок), если она есть rows = table.rows for i, row in enumerate(rows): cells = [cell.text.strip() for cell in row.cells] # Пропускаем пустые строки или заголовки if not cells or not any(cells): continue # Проверяем, что это не заголовок таблицы if i == 0 and ('имя' in cells[0].lower() or 'фамилия' in ' '.join(cells).lower()): continue # Парсим данные контакта contact = parse_contact_data(cells) # Добавляем только если есть email и данные if contact and any(contact.values()): contacts.append(contact) # Записываем в CSV файл with open('contacts.csv', 'w', encoding='utf-8', newline='') as csvfile: fieldnames = ['Имя', 'Фамилия', 'Отчество', 'Организация', 'Телефон', 'E-mail'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=';') # Записываем заголовок writer.writeheader() # Записываем все контакты writer.writerows(contacts) print(f"Успешно обработано {len(contacts)} контактов") print(f"Данные сохранены в файл contacts.csv") return contacts def export_for_gmail(): """Экспортирует контакты в формате для Gmail""" # Читаем существующий CSV файл contacts = [] with open('contacts.csv', 'r', encoding='utf-8') as csvfile: reader = csv.DictReader(csvfile, delimiter=';') contacts = list(reader) # Создаем CSV в формате Gmail with open('contacts_gmail.csv', 'w', encoding='utf-8', newline='') as csvfile: # Gmail использует специальные заголовки fieldnames = ['Name', 'Given Name', 'Additional Name', 'Family Name', 'Organization 1 - Name', 'Phone 1 - Value', 'E-mail 1 - Value'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for contact in contacts: # Очищаем название организации от многострочного текста org = contact['Организация'] if org: org = org.split('\n')[0].strip() org = re.sub(r',\s*\d{6},.*$', '', org) org = org.rstrip(',').strip() # Формируем полное имя full_name = f"{contact['Фамилия']} {contact['Имя']} {contact['Отчество']}".strip() gmail_contact = { 'Name': org if org else full_name, 'Given Name': contact['Имя'], 'Additional Name': contact['Отчество'], 'Family Name': contact['Фамилия'], 'Organization 1 - Name': org, 'Phone 1 - Value': contact['Телефон'], 'E-mail 1 - Value': contact['E-mail'] } writer.writerow(gmail_contact) print(f"\n✅ Файл для Gmail создан: contacts_gmail.csv ({len(contacts)} контактов)") print("📧 Импортируйте его в Gmail: Контакты -> Импорт -> Выберите файл") return contacts def export_for_mailru(): """Экспортирует контакты в формате для Mail.ru""" # Читаем существующий CSV файл contacts = [] with open('contacts.csv', 'r', encoding='utf-8') as csvfile: reader = csv.DictReader(csvfile, delimiter=';') contacts = list(reader) # Создаем CSV в формате Mail.ru (простой формат) with open('contacts_mailru.csv', 'w', encoding='utf-8', newline='') as csvfile: # Mail.ru использует простые заголовки fieldnames = ['First Name', 'Last Name', 'E-mail Address', 'Home Phone', 'Company'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for contact in contacts: # Очищаем название организации от многострочного текста org = contact['Организация'] if org: org = org.split('\n')[0].strip() org = re.sub(r',\s*\d{6},.*$', '', org) org = org.rstrip(',').strip() mailru_contact = { 'First Name': contact['Имя'] if contact['Имя'] else org, 'Last Name': contact['Фамилия'], 'E-mail Address': contact['E-mail'], 'Home Phone': contact['Телефон'], 'Company': org } writer.writerow(mailru_contact) print(f"\n✅ Файл для Mail.ru создан: contacts_mailru.csv ({len(contacts)} контактов)") print("📧 Импортируйте его в Mail.ru: Настройки -> Контакты -> Импорт") return contacts def export_to_vcard(): """Экспортирует контакты в формат VCard (.vcf)""" # Читаем существующий CSV файл contacts = [] with open('contacts.csv', 'r', encoding='utf-8') as csvfile: reader = csv.DictReader(csvfile, delimiter=';') contacts = list(reader) with open('contacts.vcf', 'w', encoding='utf-8') as vcf_file: for contact in contacts: # Очищаем название организации от многострочного текста org = contact['Организация'] if org: org = org.split('\n')[0].strip() org = re.sub(r',\s*\d{6},.*$', '', org) org = org.rstrip(',').strip() # Формируем VCard для каждого контакта vcf_file.write("BEGIN:VCARD\n") vcf_file.write("VERSION:3.0\n") # Имя if contact['Фамилия'] or contact['Имя']: vcf_file.write(f"FN:{contact['Фамилия']} {contact['Имя']} {contact['Отчество']}\n".strip() + "\n") vcf_file.write(f"N:{contact['Фамилия']};{contact['Имя']};{contact['Отчество']};;\n") else: # Если нет имени, используем организацию vcf_file.write(f"FN:{org}\n") # Организация if org: vcf_file.write(f"ORG:{org}\n") # Email if contact['E-mail']: vcf_file.write(f"EMAIL;TYPE=INTERNET:{contact['E-mail']}\n") # Телефон if contact['Телефон']: vcf_file.write(f"TEL;TYPE=WORK,VOICE:{contact['Телефон']}\n") vcf_file.write("END:VCARD\n") print(f"\n✅ Файл VCard создан: contacts.vcf ({len(contacts)} контактов)") print("📱 Импортируйте его в почтовый клиент или телефон") return contacts if __name__ == "__main__": print("=" * 60) print("ПАРСЕР ТЕЛЕФОННОЙ КНИГИ") print("=" * 60) # Сначала парсим Word документ print("\n📖 Парсинг телефонной книги из Word...") contacts = parse_phone_book() # Затем создаем файлы для импорта print("\n" + "=" * 60) print("СОЗДАНИЕ ФАЙЛОВ ДЛЯ ИМПОРТА") print("=" * 60) export_for_mailru() export_for_gmail() export_to_vcard() # Выводим статистику print("\n" + "=" * 60) print("ПРИМЕРЫ КОНТАКТОВ:") print("=" * 60) for i, contact in enumerate(contacts[:5], 1): org = contact['Организация'].split('\n')[0][:50] print(f"{i}. {org}... - {contact['E-mail']}") print("\n" + "=" * 60) print("✅ ГОТОВО! Используйте файлы для импорта:") print(" 📧 contacts_mailru.csv - для Mail.ru") print(" 📧 contacts_gmail.csv - для Gmail, Outlook") print(" 📱 contacts.vcf - для Apple Mail, телефонов") print("=" * 60)