Aikatsu! Je voulais utiliser la photo du visage d'un personnage pour dessiner les résultats de l'analyse de la série, mais le nombre de personnes est important et le fonctionnement manuel est gênant. J'ai donc gratté avec Beautiful Soup et Print Screen avec du sélénium. J'ai décidé de le faire automatiquement jusqu'à ce que le visage du personnage soit découpé dans PrintScreen avec OpenCV.
from urllib import request
from bs4 import BeautifulSoup
from selenium import webdriver
import pandas as pd
import time
import os
import shutil
import itertools
#OpenCV n'autorise pas les noms de fichiers japonais, donc chargez le fichier de mappage
df=pd.read_csv("C:/XXXX/aikatsu_name_romaji_mapping.tsv", sep='\t', engine='python', encoding="utf-8")
#Charger le pilote Chrome
driver = webdriver.Chrome("C:/XXXX/chromedriver/chromedriver.exe")
#Avoir une URL de tuple à gratter
character_urls =(
"http://www.aikatsu.net/01/character/index.html",
"http://www.aikatsu.net/02/character/index.html",
"http://www.aikatsu.net/03/character/index.html",
"http://www.aikatsu.net/aikatsustars_01/character/index.html",
"http://www.aikatsu.net/aikatsustars_02/character/index.html",
"http://www.aikatsu.net/aikatsufriends_01/character/",
"http://www.aikatsu.net/aikatsufriends_02/character/",
"http://www.aikatsu.net/character/"
)
#Création d'un répertoire pour stocker PrintScreen
target_dir = "C:/XXXX/download/"
if os.path.isdir(target_dir):
shutil.rmtree(target_dir)
time.sleep(1)
os.mkdir(target_dir)
Il aurait peut-être été préférable de faire de la création de répertoire une fonction.
La cartographie est aussi simple que cela.
J'utilise Pandas uniquement parce que le nombre de personnages cibles est d'environ 67 et qu'il n'est pas nécessaire de le rendre DB ou riche, et je peux le faire rapidement avec juste des connaissances.
Lorsque vous utilisez Selenium, l'emplacement de stockage du pilote est généralement défini dans la variable d'environnement, mais comme il s'agit d'un outil jetable, il n'a pas besoin d'être aussi riche. Donc, tout en faisant référence à ce qui suit, j'ai écrit le pilote en solide. Introduction à Selenium commençant avec seulement 3 lignes de python
De plus, l'erreur suivante s'est produite au moment de l'exécution.
WebDriverError: unknown error: Runtime.executionContextCreated has invalid
Cela peut être résolu en faisant correspondre la version du pilote que vous utilisez avec la version chrome car elle est différente de la version chrome.
for character_url in character_urls:
html = request.urlopen(character_url)
soup = BeautifulSoup(html, "html.parser")
#Obtenez des informations sur chaque personnage
characters=soup.find_all("a")
idol_names = [i.find('img') for i in characters]
urls = [i.get('href') for i in characters]
character_url_prefix=character_url.split("index.html")
for i, j in zip(idol_names, urls):
#Si la balise alt ne peut pas être prise correctement, le processus est rejeté.
if i == None:
continue
#Repousser les informations autres que les personnages
if j.startswith("http") or j.startswith("../") or j.startswith("index"):
continue
idol_name = i.get("alt").replace(" ","").replace(" ","")
print(idol_name)
#affichage et réglage de la page sélénium
driver.get(character_url_prefix[0]+j)
driver.set_window_size(1250, 1036)
driver.execute_script("document.body.style.zoom='90%'")
#Shirayuri Kaguya définit une valeur fixe car les informations alt sont vides
if idol_name == "":
idol_name = "Shirayuri Kaguya"
#OpenCV ne peut pas utiliser de noms japonais, alors convertissez-le en caractères romains
idol_name_romaji = df[df["character"]==idol_name]["romaji"].values[0]
file_name="{}{}.png ".format(target_dir, idol_name_romaji)
#Si un fichier du même nom existe déjà, renommez-le.
if os.path.exists(file_name):
for i in itertools.count(1):
newname = '{} ({})'.format(idol_name_romaji, i)
file_name="{}{}.png ".format(target_dir, newname)
#Quitter si le fichier du même nom n'existe pas
if not os.path.exists(file_name):
break
#Définissez un temps de sommeil légèrement plus long pour éviter les effets lors de la transition vers les pages Web
time.sleep(5)
driver.save_screenshot(file_name)
driver.quit()
Vous pouvez obtenir les données comme ceci. À l'origine, le nom japonais alt a été ajouté au nom du fichier, mais comme il ne peut pas être lu par OpenCV, il est volontairement converti en notation de caractères romains. (Romaji est approprié, vous pouvez donc faire une erreur)
De plus, lors de l'obtention des noms de personnages (idol_names), None sera obtenu comme indiqué ci-dessous. Puisque l'URL et le nom du personnage de chaque personnage sont bouclés avec zip, il est nécessaire d'avoir le même nombre d'éléments, donc j'essaye de jouer à l'intérieur plutôt qu'avant la boucle.
[<img alt="Aikatsu en parade!" src="../images/logo.png "/>,
<img alt="Aikatsu en parade! la communication" src="../images/bt-aikatsuonparadecom.png "/>,
<img alt="Aikatsu en parade! Quel est" src="../images/bt-aikatsuonparade.png "/>,
<img alt="Diffuser des informations" src="../images/bt-tvinfo.png "/>,
<img alt="personnage" src="../images/bt-character.png "/>,
<img alt="Récit" src="../images/bt-story.png "/>,
<img alt="CD" src="../images/bt-cd.png "/>,
<img alt="BD/DVD" src="../images/bt-bddvd.png "/>,
<img alt="NEWS" src="../images/bt-news.png "/>,
<img alt="TOP" src="../images/bt-top.png "/>,
<img alt="Raki Himeishi" src="images/bt-raki.png "/>,
<img alt="Yuki Aine" src="images/bt-aine.png "/>,
<img alt="Mio Minato" src="images/bt-mio.png "/>,
<img alt="Hoshimiya Ichigo" src="images/bt-ichigo.png "/>,
<img alt="Akari Ozora" src="images/bt-akari.png "/>,
<img alt="Yume Nijino" src="images/bt-yume.png "/>,
<img alt="BANDAINAMCO Pictures" height="53" src="../images/bnp.png " width="118"/>,
None]
import os
import cv2
from pathlib import Path
#Créer un annuaire
download_dir = '{0}parse/'.format(target_dir)
if os.path.isdir(download_dir):
shutil.rmtree(download_dir)
time.sleep(1)
os.mkdir(download_dir)
#Créer un classificateur basé sur le fichier de quantité d'objets
classifier = cv2.CascadeClassifier('C:/XXX/lbpcascade_animeface.xml')
#Récupérez les fichiers dans le répertoire récupéré
p = Path(target_dir)
for i in list(p.glob("*.png ")):
#Détection facial
image = cv2.imread(i.as_posix())
#Créer un annuaire
file_tmp=i.as_posix().split("/")
parse_dir = '{0}{1}/'.format(download_dir, file_tmp[len(file_tmp)-1:len(file_tmp)][0].split(".")[0])
os.mkdir(parse_dir)
#Échelle de gris
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(gray_image)
for i, (x,y,w,h) in enumerate(faces):
#Découpez les faces une à une. Ajustez la coordonnée y pour la rendre rectangulaire
face_image = image[y-50:y+h, x:x+w]
output_path = '{0}{1}.png'.format(parse_dir, i)
#l'écriture
cv2.imwrite(output_path ,face_image)
Je voulais qu'OpenCV soit rectangulaire, j'ai donc juste modifié un peu les coordonnées et le contenu est le suivant. Détection de visage d'anime avec OpenCV
Vous pouvez l'obtenir comme ça. En raison de la pose, certains d'entre eux n'ont pas été identifiés comme des personnages par le classificateur. Comme il n'y a que quelques personnes, je me demande si je dois le faire manuellement.
Recommended Posts