LoginSignup
0
3

More than 1 year has passed since last update.

「ポケモンずかん」自主制作(SV対応1008種1226匹)

Last updated at Posted at 2023-02-25

SV含む全モンスターを網羅した書籍がないためコードを書きました。
※私的利用目的です。コードの利用に関して一切責任は取りません。

「ポケモンずかん」から画像と情報を取得

download.ipynb
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import urllib.error
import urllib.request
import time
import re
import os
import json

#画像の保存場所
download_dir = 'pokemon'

#ユーザーエージェント設定(コピペOK)
ua = 'Mozilla/5.0(Macintosh; Intel Mac Os X 10_12_3)'
'AppleWebKit/537.3.(KHTML,Like Gecko)'
'Chrome/55.0.2883.95 Safari/537.36'

#画像のURLにアクセスして保存する関数
def download_img(url,dst_path):
    try:
        data = urllib.request.urlopen(url).read()
        with open(dst_path,mode='wb') as f:
            f.write(data)

    except urllib.error.URLError as e:
        print("エラーが発生しました")
        print(e)

#0001~1008までのリストを作成
number_list = {'{:04}'.format(i) for i in range(1,1009)}
#ポケモンずかんのURLの取得
url_list = ['https://zukan.pokemon.co.jp/detail/{0}'.format(number) for number in number_list]
for url_base in url_list:
    time.sleep(1)
    for i in range(10): #同一no.多種ポケモン(フォルム違い)をチェックするため十分大きい数
        if i > 0:
            url = url_base + '-' + str(i)
        else:
            url = url_base
        
        #URLのHTMLから各種データが入ったjsonを取得
        req = urllib.request.Request(url,headers = {'User-Agent':ua})
        html = urllib.request.urlopen(req)
        soup = BeautifulSoup(html,"html.parser")
        script_text = soup.find(id="json-data").get_text()
        data = json.loads(script_text)

        #画像のURLを取得
        images_url = data["pokemon"]['image_m']

        #ナンバーを取得
        number = str(data["pokemon"]['no'])
        sub_number = str(data["pokemon"]['sub'])
        
        #名前を取得
        name = data["pokemon"]['name']
        sub_name = data["pokemon"]['sub_name']
        
        #タイプを取得
        type_1 = str('{:02}'.format(int(data["pokemon"]['type_1'])))
        type_2 = str('{:02}'.format(int(data["pokemon"]['type_2'])))
        
        #保存ファイル名の設定
        dst_path = os.path.join(download_dir + '/' + number + '-' + sub_number + '_' + name + '_' + sub_name + '_' + type_1 + '_' + type_2 + '.png')

        #画像保存
        download_img(images_url,dst_path)

        print(name + ' ' + sub_name + ' ' + number + ' ' + sub_number + ' ' + type_1 + ' ' + type_2)
            
        # フォルム違いの有無チェック
        if len(data["groups"]) == 0:
            break
        # フォルム違い全てチェックするまでループ
        if len(data["groups"])-2 < i:
            break

print("処理が完了しました")

画像に情報を追記

edit.ipynb
# -*- coding: utf-8 -*-
import sys
import os
from PIL import Image, ImageDraw, ImageFont
import pathlib
import re

input_dir = "./pokemon/"
output_dir = "./pokemon_edited/"

#編集後の画像の格納先が存在しなければ作る
if os.path.isdir(output_dir) == False:
    os.makedirs(output_dir)

def add_margin(pil_img, top, right, bottom, left, color):
    width, height = pil_img.size
    new_width = width + right + left
    new_height = height + top + bottom
    result = Image.new(pil_img.mode, (new_width, new_height), color)
    result.paste(pil_img, (left, top))
    return result
    
#タイプ管理番号とタイプの対応辞書
type_dic = {'00':'', '01':'ノーマル', '02':'ほのお', '03':'みず', '04':'くさ', '05':'でんき', '06':'こおり', '07':'かくとう', '08':'どく', '09':'じめん',
            '10':'ひこう', '11':'エスパー', '12':'むし', '13':'いわ', '14':'ゴースト', '15':'ドラゴン', '16':'あく', '17':'はがね', '18':'フェアリー'} 

files = os.listdir(input_dir)
for file in files:
    #各種情報を画像に書き込む際のフォント定義
    font = ImageFont.truetype('C:/Windows/Fonts/meiryo.ttc', 33)
    
    #png画像の背景を白色に、各種情報を書き込むマージン(余白)を周囲に追加
    png = Image.open(os.path.join(input_dir, file))
    png.load() # required for png.split()
    img = Image.new("RGB", png.size, (255, 255, 255)) # 背景色
    img.paste(png, mask=png.split()[3]) # 3 is the alpha channel
    img = add_margin(img, 35, 35, 35, 35, (255, 255, 255))
    
    draw = ImageDraw.Draw(img)
    
    #画像に枠線を追加
    w, h = img.size
    draw.rectangle((0, 0, w-1, h-1), outline = (0, 0, 0))
    
    #図鑑no.を記載
    file_name_item = re.split('[_.]', file)
    draw.text((10, 0), file_name_item[0][:4], '#000000', font=font, anchor='la') #number
    
    #ポケモン名、フォルム名を記載 ※「キョダイマックスのすがた」は「キョダイマックス」に変更
    if file_name_item[2]=='':
        pad_beg = ''
        pad_end = ''
    else:
        pad_beg = ' ('
        pad_end = ')'
    if len(file_name_item[2]) > 14: #ポケモン名+フォルム名が長いと画像に入りきらないためフォントサイズ変更
        font = ImageFont.truetype('C:/Windows/Fonts/meiryo.ttc', 28)
    draw.text((320, 642), file_name_item[1] + pad_beg + file_name_item[2].replace('キョダイマックスのすがた','キョダイマックス') + pad_end, '#000000', font=font, anchor='md')
    
    #タイプを記載
    if file_name_item[4]=='00':
        pad = ''
    else:
        pad = '  '
    draw.text((630, 0), type_dic[file_name_item[3]] + pad + type_dic[file_name_item[4]], '#000000', font=font, anchor='ra')
    
    #画像を保存
    img.save(os.path.join(output_dir, file_name_item[0] + '.png'))

画像をタイル状に並べる

tile.ipynb
# -*- coding: utf-8 -*-
import os
import cv2
import numpy as np
from PIL import Image, ImageDraw

#タイル状に並べる際の縦横枚数
tile_col = 4
tile_row = 6
tile_num = tile_col * tile_row

input_dir = "./pokemon_edited/"
output_dir = "./pokemon_tile/"

#編集後の画像の格納先が存在しなければ作る
if os.path.isdir(output_dir) == False:
    os.makedirs(output_dir)

#画像をタイル状に並べる関数
def concat_tile(im_list_2d):
    return cv2.vconcat([cv2.hconcat(im_list_h) for im_list_h in im_list_2d])

files = os.listdir(input_dir)

#最後のタイル状画像に足りないブランク画像の生成
img = cv2.imread(os.path.join(input_dir, files[0]))
blank = np.full(img.shape, 255)
h, w, c = blank.shape
cv2.rectangle(blank, (0, 0), (w-1, h-1), (0, 0, 0))
for i in range((len(files)//tile_num+1)*tile_num-len(files)):
    cv2.imwrite(os.path.join(input_dir, str(9000+i)+'.png'), blank) #blank画像処理は9000番台に

#関数concat_tileに渡す画像群array(tile_col*tile_row)の生成
img_array = []
img_list = []
cnt = 0
for i in range(1,len(files)+1):
    img = cv2.imread(os.path.join(input_dir, files[i-1]))
    img_list.append(img)
    if i%tile_col==0:
        img_array.append(img_list)
        img_list = [] #リスト(各rowの画像群)の初期化
    if i%tile_num==0:
        img_tile = concat_tile(img_array)
        h, w, c = img_tile.shape
        cv2.rectangle(img_tile, (1, 1), (w-3, h-4), (0, 0, 0)) #生成したタイル状画像の外枠 ※必要であれば
        cnt+=1
        #タイル状画像の保存
        cv2.imwrite(os.path.join(output_dir, str('{:02}'.format(cnt))+'.png'), img_tile)
        img_array = [] #リスト(col*rowの画像群)の初期化
0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3