201 lines
No EOL
9.6 KiB
Python
201 lines
No EOL
9.6 KiB
Python
import json
|
||
import os
|
||
import time
|
||
import openpyxl
|
||
from kivy.app import App
|
||
from kivy.uix.label import Label
|
||
from kivy.uix.button import Button
|
||
from kivy.uix.boxlayout import BoxLayout
|
||
from kivy.uix.popup import Popup
|
||
from kivy.uix.filechooser import FileChooserListView
|
||
from selenium import webdriver
|
||
from selenium.webdriver.common.by import By
|
||
from selenium.webdriver.common.keys import Keys
|
||
from selenium.webdriver.chrome.options import Options
|
||
from selenium.webdriver.support.ui import WebDriverWait
|
||
from selenium.webdriver.support import expected_conditions as EC
|
||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||
|
||
# Файл конфигурации для сохранения последнего пути
|
||
CONFIG_FILE = 'config.json'
|
||
|
||
def get_last_used_directory():
|
||
"""Возвращает последний использованный каталог из файла конфигурации."""
|
||
if os.path.exists(CONFIG_FILE):
|
||
with open(CONFIG_FILE, 'r') as file:
|
||
config = json.load(file)
|
||
return config.get('last_dir', '')
|
||
return ''
|
||
|
||
def save_last_used_directory(directory):
|
||
"""Сохраняет последний использованный каталог в файл конфигурации."""
|
||
with open(CONFIG_FILE, 'w') as file:
|
||
json.dump({'last_dir': directory}, file)
|
||
|
||
def get_search_key(filename):
|
||
"""
|
||
Преобразует имя файла: удаляет расширение и заменяет дефисы на подчёркивания.
|
||
Например, "3M-Protemp4-Banner-900x450-BG.jpg" превращается в "3M_Protemp4_Banner_900x450_BG".
|
||
"""
|
||
if not filename:
|
||
return ""
|
||
base = os.path.splitext(filename)[0]
|
||
return base.replace("-", "_")
|
||
|
||
class FileSearchApp(App):
|
||
def build(self):
|
||
self.file_path = ""
|
||
self.extensions = [".psd", ".indd", ".tif", ".tiff"]
|
||
|
||
layout = BoxLayout(orientation='vertical')
|
||
self.label = Label(text="Select an Excel file with Asset IDs")
|
||
layout.add_widget(self.label)
|
||
|
||
choose_button = Button(text="Choose File")
|
||
choose_button.bind(on_press=self.select_file)
|
||
layout.add_widget(choose_button)
|
||
|
||
start_button = Button(text="Open Login Page")
|
||
start_button.bind(on_press=self.open_login_page)
|
||
layout.add_widget(start_button)
|
||
|
||
self.continue_button = Button(text="Continue After Login", disabled=True)
|
||
self.continue_button.bind(on_press=self.start_search)
|
||
layout.add_widget(self.continue_button)
|
||
|
||
return layout
|
||
|
||
def select_file(self, instance):
|
||
last_dir = get_last_used_directory() or '.'
|
||
filechooser = FileChooserListView(path=last_dir, filters=['*.xlsx'])
|
||
popup = Popup(title="Choose Excel File", content=filechooser, size_hint=(0.9, 0.9))
|
||
filechooser.bind(on_submit=lambda chooser, selection, touch: self.on_file_select(selection, popup))
|
||
popup.open()
|
||
|
||
def on_file_select(self, selection, popup):
|
||
if selection:
|
||
self.file_path = selection[0]
|
||
self.label.text = f"Selected File: {self.file_path}"
|
||
print(f"Selected file: {self.file_path}")
|
||
save_last_used_directory(os.path.dirname(self.file_path))
|
||
popup.dismiss()
|
||
else:
|
||
print("No file selected.")
|
||
|
||
def open_login_page(self, instance):
|
||
if not self.file_path:
|
||
popup = Popup(title='Warning',
|
||
content=Label(text='Select a file before starting!'),
|
||
size_hint=(0.8, 0.3))
|
||
popup.open()
|
||
return
|
||
options = Options()
|
||
options.add_argument("user-data-dir=/Users/vadymsamoilenko/Library/Application Support/Google/Chrome/Profile 1")
|
||
self.driver = webdriver.Chrome(options=options)
|
||
try:
|
||
self.driver.get("https://mmmspinco.brand-portal.adobe.com/mediaportal.html/content/dam/mac/mmmspinco")
|
||
time.sleep(5)
|
||
WebDriverWait(self.driver, 30).until(
|
||
EC.presence_of_element_located((By.XPATH, "/html/body/coral-shell/coral-shell-content/div[1]/a/img"))
|
||
)
|
||
self.continue_button.disabled = False
|
||
print("Login successful, ready to continue.")
|
||
login_popup = Popup(title='Login',
|
||
content=Label(text='Please log in and complete 2FA.\nClick "Continue After Login" once logged in.'),
|
||
size_hint=(0.8, 0.3))
|
||
login_popup.open()
|
||
except Exception as e:
|
||
print("Error opening login page:", e)
|
||
self.driver.quit()
|
||
|
||
def start_search(self, instance):
|
||
if not self.file_path or self.continue_button.disabled:
|
||
popup = Popup(title='Warning',
|
||
content=Label(text='Ensure you are logged in before starting!'),
|
||
size_hint=(0.8, 0.3))
|
||
popup.open()
|
||
return
|
||
try:
|
||
wb = openpyxl.load_workbook(self.file_path)
|
||
sheet = wb.active
|
||
|
||
# Предполагаем, что:
|
||
# - Столбец 1: Asset ID
|
||
# - Столбец 3: Имя файла (с расширением)
|
||
for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row):
|
||
asset_id = row[0].value # Asset ID
|
||
file_name = row[2].value if len(row) >= 3 else None # Имя файла
|
||
found_link = None
|
||
if asset_id and file_name:
|
||
search_key = get_search_key(file_name)
|
||
print(f"Processing Asset ID: {asset_id} with search key: {search_key}")
|
||
|
||
self.driver.get("https://mmmspinco.brand-portal.adobe.com/aem/search.html")
|
||
search_box = WebDriverWait(self.driver, 10).until(
|
||
EC.presence_of_element_located((By.NAME, "fulltext"))
|
||
)
|
||
# Очистка поля ввода через clear() и JavaScript
|
||
time.sleep(3)
|
||
search_box.clear()
|
||
self.driver.execute_script("arguments[0].value = '';", search_box)
|
||
|
||
# Поиск по asset_id для первоначального отбора
|
||
search_box.send_keys(asset_id)
|
||
search_box.send_keys(Keys.RETURN)
|
||
time.sleep(3)
|
||
|
||
try:
|
||
properties_button = WebDriverWait(self.driver, 30).until(
|
||
EC.element_to_be_clickable((By.XPATH, "//button/coral-icon[@icon='infoCircle']"))
|
||
)
|
||
properties_button.click()
|
||
time.sleep(3)
|
||
|
||
# Получаем все PSD-ссылки из секции "Others"
|
||
psd_link_elements = WebDriverWait(self.driver, 30).until(
|
||
EC.presence_of_all_elements_located(
|
||
(By.XPATH, "//div[contains(@class, 'references-referencing')]//a[@data-relation='others' and contains(@data-asset-path, '.psd')]")
|
||
)
|
||
)
|
||
time.sleep(3)
|
||
# Выводим отладочную информацию для каждого кандидата
|
||
for elem in psd_link_elements:
|
||
title_attr = elem.get_attribute("title")
|
||
href = elem.get_attribute("href")
|
||
print(f"Candidate element -> title: {title_attr}, href: {href}")
|
||
# Выбираем элемент, где search_key встречается в title или href (без учета расширения)
|
||
for elem in psd_link_elements:
|
||
title_attr = elem.get_attribute("title")
|
||
href = elem.get_attribute("href")
|
||
search_key_lower = search_key.lower()
|
||
if (search_key_lower in title_attr.lower() if title_attr else False) or \
|
||
(search_key_lower in href.lower() if href else False):
|
||
found_link = href
|
||
print(f"Selected link matching search key: {found_link}")
|
||
break
|
||
except TimeoutException:
|
||
print("Timeout while waiting for the PSD link element.")
|
||
found_link = None
|
||
except NoSuchElementException:
|
||
print("PSD link element not found.")
|
||
found_link = None
|
||
except Exception as e:
|
||
print(f"Unexpected error occurred: {e}")
|
||
found_link = None
|
||
|
||
if not found_link:
|
||
print("No suitable link found for asset:", asset_id)
|
||
|
||
sheet.cell(row=row[0].row, column=2, value=found_link if found_link else "Links not found")
|
||
print(f"Processed asset {asset_id}, link: {found_link}")
|
||
save_path = self.file_path.replace(".xlsx", "_updated.xlsx")
|
||
wb.save(save_path)
|
||
success_popup = Popup(title='Success',
|
||
content=Label(text=f"File saved: {save_path}"),
|
||
size_hint=(0.8, 0.3))
|
||
success_popup.open()
|
||
finally:
|
||
self.driver.quit()
|
||
|
||
if __name__ == '__main__':
|
||
FileSearchApp().run() |