Скрипт Python для автоматизации извлечения ссылок на документы из сети компании и записи в файл ExcelPython

Программы на Python
Ответить
Anonymous
 Скрипт Python для автоматизации извлечения ссылок на документы из сети компании и записи в файл Excel

Сообщение Anonymous »

Я завершаю работу над базой данных в формате XLSX, содержащей все продукты моей компании, где я прохожу стажировку. В частности, я создал столбец, куда вставляю одну за другой ссылки, ведущие на пользовательские листы, а также технические листы этих продуктов. Эти ссылки будут прочитаны и обработаны локальной моделью искусственного интеллекта, которую я позже вызову в своем конвейере Python, чтобы обработать семантическое сходство между каждым документом.
Существует 330 продуктов, и выполнение этого вручную занимает очень много времени. Поэтому я попытался создать сценарий извлечения Python, используя ChatGPT и Gemini. Я методично описывал им, что я делал вручную, шаг за шагом, для данного продукта, чтобы они могли предложить мне сценарий извлечения.
Вот подсказки, данные GPT и Gemini:

"CONTEXTE:

Je veux insérer des Liens presents sur le réseau de mon entreprise dans la feuille "master_file" de Мой класс «product_catalog_V8_links» ci-joint. Les Liens Menant aux Fichiers PDF-содержимое уведомлений об использовании в местах в столбце M («инструкции_по_использованию»), а также в том, что они содержат документы по методам проверки в столбце N («Файл_проверки»).. La logique que je suis Ручное управление:
1. Я вошел в сеть через ссылку «\\dc2022adia\BioxAdia\R11_Marketing\0_Library»
2. Я нашел в колонке «master_file» референсный продукт. recherchée — это дебют клетки в вязании крючком (например: «[ADI631-100] ADIAVET SALMONELLA ST/SE FAST TIME 100R» в столбце A86) (см. снимок экрана «1» в PJ)
3. код продукта является «базовым», без каких-либо условий (например: ADI631-100, отличающийся от ADI631)
4. j’obtiens ensuite:
a.
5. je clique sur le dossier (cas a.) s’il apparaît (см. снимок экрана «2» в PJ) J’ouvre ensuite les dossiers enfants «Dossier de validation» и «Notices» dans un nouvel onglet avec un clic droit.
6. В «Уведомлениях» есть ответ на 2 критерия:
a. На английском языке (обязательно) Эти документы указаны с учетом соответствующих критериев:
i (EN) écrit vers la fin du nom du fichier, avant le numéro de version (пример: ADC22LD-CSFV-NO-(EN)-V01.pdf )
ii. NE écrit en début de fichier (например: NE014S-03.pdf) b. последняя версия (если указан номер версии, указанный в соответствующем документе): i. ADC72LD-EHDV-NO-(EN)-V02.pdf) ii. -xx.pdf в окончательном описании (например: NE601-01.pdf)
iii. Это не точное указание на критерий проверки.
7. pas de fichier repondant aux critères 6. C’est le cas ici (см. снимок экрана «3») Je constate ici qu’il n’y aucun fichier repondant au critère 6)a. Ma recherche s’arrête alors pour la note de la cellule / produit A86 et je marque en rouge (couleur de remplissage). ячейка «instructions_for_use» относительно ячейки/продукта A86 на работе, так же как и ячейка M86 (см. 7.a на экране «4»).
b. «ADI631-STSE-DV-(FR)-V01» меня удовлетворяет, поэтому я хочу щелкнуть «право объекта» > «собственность» > «безопасность». Я скопирую «имя объекта» (см. снимок экрана «4»), который вставлен в гипертекст в ячейке «инструкции_по_использованию» относительно ячейки /. производите A86 на работе, используйте ячейку M86 (см. 7.b на снимке экрана 4).
8. Я прохожу через «Досье проверки» ячейки / продукт A86 для повторения процедуры мема, которую нужно выполнить для «уведомлений» в этом месте. Рисунок или досье ячейки/продукта A86 содержат досье под названием «Досье валидации». Il faut note les suivantes différences:
а. На вкладке залоговых документов в колонку N де-ля-файл «master_file», в отличие от залоговых документов «instructions_for_use», которые вписаны в колонку M.
b. écriture на английском языке:
i. -en en fin de fichier (например: R262-C-en.pdf)
ii. (EN) écrit vers la fin du nom du fichier, avant le numéro de version (пример: ADI045-PTUB-DV-(EN)-V01.pdf) На рисунке или в досье ячейки/продукта A86 не содержится па-де-де-досье под именем «Досье проверки», на прошедшем этапе. l'étape 9.
9. Для того, чтобы сделать шаг 8. я прошел через ячейку / продукт A87 и т. д. просто сделайте последнюю ячейку / продукт из колонны A (A338).
Если вы не хотите получить этот продукт, вы не можете получить эти документы. l’étape 4 (casminoritaire), напишите фиолетовую метку (couleur de remplissage) на ячейке «instructions_for_use» на модели l’étape 7.a, затем нажмите на соответствующий продукт (cf étape 9).
ЦЕЛЬ: Предложить мой сценарий Python для автоматизации всего этого procédure"
Вот что мне дал GPT:

Код: Выделить всё

import re
from pathlib import Path
from collections import defaultdict
from openpyxl import load_workbook
from openpyxl.styles import PatternFill

# =========================
# CONFIG
# =========================
LIBRARY_ROOT = Path(r"\\[NETWORK PATH]")
MASTER_PATH = Path("product_catalog_V8.xlsx")
MASTER_SHEET = "master_file"

COL_PRODUCT_CODE = "A"
COL_NOTICE = "M"
COL_VALIDATION = "N"

RED_FILL = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")

# =========================
# UTILS
# =========================
BASE_CODE_RE = re.compile(r"^([A-Z]+\d+)")
VERSION_RE = re.compile(r"V0*(\d+)", re.IGNORECASE)

def extract_base_code(code: str) -> str | None:
if not code:
return None
m = BASE_CODE_RE.match(code.strip())
return m.group(1) if m else None

def extract_version(path: Path) -> int | None:
m = VERSION_RE.search(path.name)
return int(m.group(1)) if m else None

# =========================
# INDEXATION
# =========================
def build_index(root: Path):
index = defaultdict(lambda: {"notice": [], "validation": []})

for pdf in root.rglob("*.pdf"):
p = str(pdf)
if "\\Notices\\" in p:
kind = "notice"
elif "\\Dossier de validation\\" in p:
kind = "validation"
else:
continue

if "EN"  not in pdf.name.upper():
continue

base_match = BASE_CODE_RE.search(pdf.name)
if not base_match:
continue

base_code = base_match.group(1)
version = extract_version(pdf)

if version is None:
continue

index[base_code][kind].append((version, pdf))

return index

# =========================
# RESOLUTION
# =========================
def resolve_best(files):
if not files:
return None
return max(files, key=lambda x: x[0])[1]

# =========================
# MAIN
# =========================
def main():
print("Indexation réseau…")
index = build_index(LIBRARY_ROOT)
print(f"{len(index)} produits indexés")

wb = load_workbook(MASTER_PATH)
ws = wb[MASTER_SHEET]

for row in range(2, ws.max_row + 1):
code_cell = ws[f"{COL_PRODUCT_CODE}{row}"]
notice_cell = ws[f"{COL_NOTICE}{row}"]
validation_cell = ws[f"{COL_VALIDATION}{row}"]

if notice_cell.value or validation_cell.value:
continue

base_code = extract_base_code(str(code_cell.value))
if not base_code or base_code not in index:
notice_cell.fill = RED_FILL
validation_cell.fill = RED_FILL
continue

notice = resolve_best(index[base_code]["notice"])
validation = resolve_best(index[base_code]["validation"])

if not notice or not validation:
notice_cell.fill = RED_FILL
validation_cell.fill = RED_FILL
continue

notice_cell.value = notice.as_posix()
validation_cell.value = validation.as_posix()

wb.save(MASTER_PATH)
print("Terminé.")

if __name__ == "__main__":
main()
Вывод: столбцы M и N моего файла Excel были заполнены только красными ячейками!
Вот что предложил мне Gemini:

Код: Выделить всё

import pandas as pd
import os
import re

# --- CONFIGURATION ---
# Chemin vers votre fichier Excel
excel_path = 'product_catalog_V8_links.xlsx'

# Chemin racine du réseau (Note : utilisez r'' pour les chemins Windows)
root_folder_path = r'[NETWORK PATH]

# Noms des colonnes dans Excel
col_reference = 'Reference'
col_notice = 'instructions_for_use'
col_validation = 'Validation_file'

# --- FONCTION DE RECHERCHE ---
def find_files_for_ref(ref_id, root_path):
"""
Cherche les chemins des fichiers Notice et Validation pour un ID donné.
Retourne un dictionnaire avec les chemins trouvés.
"""
paths = {'notice': None, 'validation': None}

# Nettoyage de la référence : on garde ce qu'il y a entre crochets ou la ref brute
# Ex: "[#416443]" -> "416443" ou "ADI015"
clean_ref = str(ref_id).replace('[', '').replace(']', '').split(']')[0].strip()

# Si la référence est vide ou trop courte, on ignore pour éviter les faux positifs
if len(clean_ref) < 3:
return paths

# 1. On cherche d'abord le dossier du produit correspondant à la ref
product_folder_path = None

# os.walk permet de descendre dans toute l'arborescence (ORT, BVD, etc.)
for root, dirs, files in os.walk(root_path):
for dir_name in dirs:
# Si le nom du dossier contient la référence (ex: "416443-ADIAVET ORT" contient "416443")
if clean_ref.lower() in dir_name.lower():
product_folder_path = os.path.join(root, dir_name)
break
if product_folder_path:
break

# Si aucun dossier produit n'est trouvé, on arrête là
if not product_folder_path:
return paths

# 2.  Une fois dans le bon dossier produit, on cherche les sous-dossiers spécifiques
# On regarde dans le dossier produit et ses sous-dossiers immédiats
for root, dirs, files in os.walk(product_folder_path):

# Recherche NOTICE
if "notice" in root.lower() or "notices" in root.lower():
for file in files:
if file.lower().endswith('.pdf'):
# On prend le chemin absolu
paths['notice'] = os.path.join(root, file)
break # On prend le premier PDF trouvé

# Recherche VALIDATION
if "validation" in root.lower() or "dossier de validation" in root.lower():
for file in files:
if file.lower().endswith('.pdf'):
paths['validation'] = os.path.join(root, file)
break

return paths

# --- EXÉCUTION ---
print("Chargement du fichier Excel...")
# On charge l'onglet 'master_file' (ajustez le sheet_name si besoin)
df = pd.read_excel(excel_path, sheet_name='master_file')

print(f"Début du traitement de {len(df)} lignes. Cela peut prendre du temps sur un réseau...")

# On itère sur chaque ligne
for index, row in df.iterrows():
ref = row[col_reference]

# On ne traite que si la ref n'est pas vide
if pd.notna(ref):
print(f"Recherche pour : {ref} ...")
found_paths = find_files_for_ref(ref, root_folder_path)

# Si on trouve une Notice, on l'écrit
if found_paths['notice']:
df.at[index, col_notice] = found_paths['notice']
print(f"   -> Notice trouvée : {os.path.basename(found_paths['notice'])}")

# Si on trouve une Validation, on l'écrit
if found_paths['validation']:
df.at[index, col_validation] = found_paths['validation']
print(f"   -> Validation trouvée : {os.path.basename(found_paths['validation'])}")

# --- SAUVEGARDE ---
output_file = 'product_catalog_V8_links_UPDATED.xlsx'
print(f"Sauvegarde dans {output_file}...")
df.to_excel(output_file, index=False, sheet_name='master_file')
print("Terminé !")
Вывод: во входном файле ничего не изменилось!
Есть идеи, как заставить работать любое из этих двух предложений?

Заранее спасибо!

Подробнее здесь: https://stackoverflow.com/questions/798 ... omapany-ne
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»