初めに
これが
'<span style="color: #0000FF">これが青い</span>、またhogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehoge<span class="font-bold" style="color: #FEDCBA">別の色</span>、<span class="font-bold" style="color: #777777">これがグレー</span>、<span class="font-bold" style="color: #FFFF00">これが黄色い</span>、',
HTMLを処理して何かするときに使えます。
仕様
<span ~ から始まる部分を探して、その中身を指定された色で描画できます。divだったりclassで指定されてる場合は適宜置き換えてください。
例:
<div class="red_txt">hoge</div>
だった場合、cssなどから色を取得して置き換える
<span style="color: #FF0000">hoge</span>
コード
以下がコードになります。
main.py
def despan_draw(draw, font_file, text, font_size, starcord):
x_pos = starcord[0]
y_pos = starcord[1]
pattern = re.compile(
r'<span[^>]*style="color: #[a-zA-Z0-9].....">(.*?)<\/span>',
re.DOTALL,
)
lines = text.split("\n")
for line in lines:
if "<span" in line:
amount = line.count("<span")
for i in range(amount):
start_idx = line.find("<span")
end_idx = line.find("</span>")
if start_idx != -1 and end_idx != -1:
style = line[start_idx : end_idx + 7] # '<span ... </span>' の部分
color_start_idx = style.find("color:")
if color_start_idx != -1:
color_hex = style[color_start_idx + 8 : color_start_idx + 14]
text_color = tuple(
int(color_hex[i : i + 2], 16) for i in (0, 2, 4)
)
# マッチした部分を抽出
match = pattern.search(line)
if match:
x = x_pos
span_text = match.group(1)
line = pattern.sub(rf"{span_text}", line, count=1)
span_start = line.find(span_text)
ct = 0
for char in line:
if char == "<":
x_pos = x
break
line = line[1:]
if ct >= span_start and ct < span_start + len(span_text):
char_color = text_color
else: # その他の部分
char_color = (255, 255, 255)
draw.text(
(x, y_pos),
char,
fill=char_color,
font=ImageFont.truetype(font_file, font_size),
)
char_bbox = draw.textbbox(
(x, y_pos),
char,
font=ImageFont.truetype(font_file, font_size),
)
char_width = char_bbox[2] - char_bbox[0]
x += char_width
ct += 1
# ここで改行もできる(適宜調整)
if x >= 2000:
x = starcord[0]
y_pos += font_size
else:
# 普通の文字列
draw.text(
(int(x_pos), int(y_pos)),
line,
fill=(255, 255, 255),
font=ImageFont.truetype(font_file, font_size),
)
y_pos += font_size
x_pos = starcord[0]
上記の関数を呼び出すことで描画されます。
main.py
def draw_image(font_file):
canvas = Image.new("RGBA", (2048, 1024), (255, 255, 255, 0))
draw = ImageDraw.Draw(canvas)
despan_draw(
draw,
font_file,
'<span class="font-bold" style="color: #0000FF">これが青い</span>、またhogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehogehoge<span class="font-bold" style="color: #FEDCBA">別の色</span>、<span class="font-bold" style="color: #777777">これがグレー</span>、<span class="font-bold" style="color: #FFFF00">これが黄色い</span>、',
20,
(50, 100),
)
canvas.save("test.png")
print("保存:test.png")