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

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

# 「ポケモンずかん」から画像と情報を取得
```python: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("処理が完了しました")

```
# 画像に情報を追記
```python: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'))
```
# 画像をタイル状に並べる
```python: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の画像群）の初期化
```