Skip to main content
Glama
wordcloud_generator.py6.21 kB
"""WordCloud画像生成モジュール.""" import logging import random from pathlib import Path from typing import Optional import matplotlib import matplotlib.pyplot as plt from wordcloud import WordCloud # matplotlibのバックエンドをAggに設定(GUI不要) matplotlib.use("Agg") logger = logging.getLogger(__name__) class WordCloudGenerator: """WordCloud画像生成を行うクラス. 日本語対応のWordCloudを生成し、美しいカラースキームを適用します。 """ def __init__(self): """初期化.""" self.default_font = self._get_japanese_font() self.color_schemes = {"accenture": self._accenture_color_func, "default": None} def generate( self, text_or_frequencies: str | dict[str, int], output_path: Optional[str] = None, color_scheme: str = "accenture", width: int = 1200, height: int = 600, ) -> str: """WordCloudを生成. Args: text_or_frequencies: WordCloud生成元のテキストまたは頻度辞書 output_path: 画像出力パス(省略時は一時ファイル) color_scheme: カラースキーム('accenture' or 'default') width: 画像幅 height: 画像高さ Returns: str: 生成された画像のパス Raises: ValueError: データが空の場合 """ # 入力チェック if isinstance(text_or_frequencies, dict): if not text_or_frequencies: raise ValueError("頻度辞書が空です") logger.info(f"WordCloud生成開始: {len(text_or_frequencies)}語の頻度辞書") elif isinstance(text_or_frequencies, str): if not text_or_frequencies or not text_or_frequencies.strip(): raise ValueError("テキストが空です") logger.info(f"WordCloud生成開始: {len(text_or_frequencies)}文字") else: raise ValueError("テキストまたは頻度辞書を指定してください") # カラー関数取得 color_func = self.color_schemes.get(color_scheme, None) # WordCloud生成 wordcloud = WordCloud( width=width, height=height, background_color="#F8F8F8" if color_scheme == "accenture" else "white", font_path=self.default_font, color_func=color_func, prefer_horizontal=0.7, relative_scaling=0.5, min_font_size=10, ) # 頻度辞書またはテキストから生成 if isinstance(text_or_frequencies, dict): wordcloud.generate_from_frequencies(text_or_frequencies) else: wordcloud.generate(text_or_frequencies) # 画像保存 if output_path is None: output_path = "wordcloud.png" output_file = Path(output_path) output_file.parent.mkdir(parents=True, exist_ok=True) plt.figure(figsize=(width / 100, height / 100), facecolor="#F8F8F8" if color_scheme == "accenture" else "white") plt.imshow(wordcloud, interpolation="bilinear") plt.axis("off") plt.tight_layout(pad=0) plt.savefig( output_file, format="png", dpi=100, bbox_inches="tight", facecolor="#F8F8F8" if color_scheme == "accenture" else "white" ) plt.close() logger.info(f"WordCloud生成完了: {output_file}") return str(output_file) def _get_japanese_font(self) -> Optional[str]: """日本語フォントパスを取得. Returns: Optional[str]: フォントパス(見つからない場合はNone) """ # Windows環境での日本語フォント候補 font_candidates = [ "C:\\Windows\\Fonts\\msgothic.ttc", # MSゴシック "C:\\Windows\\Fonts\\meiryo.ttc", # メイリオ "C:\\Windows\\Fonts\\yugothm.ttc", # 游ゴシック # Linux環境 "/usr/share/fonts/truetype/fonts-japanese-gothic.ttf", "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", # macOS環境 "/System/Library/Fonts/ヒラギノ角ゴシック W3.ttc", "/Library/Fonts/Hiragino Sans GB.ttc", ] for font_path in font_candidates: if Path(font_path).exists(): logger.info(f"日本語フォント検出: {font_path}") return font_path logger.warning("日本語フォントが見つかりません。デフォルトフォントを使用します。") return None def _accenture_color_func(self, word=None, font_size=None, position=None, orientation=None, font_path=None, random_state=None): """パープルグラデーションカラー関数. パープルグラデーション(#A100FF → #6B00B6)のカラースキームを生成します。 Returns: str: RGB文字列 """ # パープルグラデーションの色リスト purple_colors = [ (161, 0, 255), # #A100FF (139, 0, 230), (107, 0, 182), # #6B00B6 (201, 102, 255), # #C966FF (lighter) (180, 50, 255), ] # random_stateを使用して決定的に色を選択 # 単語のハッシュ値から色を決定(再現性を持たせる) if word: idx = hash(word) % len(purple_colors) elif random_state is not None: # numpy.random.RandomStateオブジェクトの場合 if hasattr(random_state, 'randint'): idx = random_state.randint(0, len(purple_colors)) # 念のため範囲チェック idx = min(idx, len(purple_colors) - 1) else: # 整数などの場合 idx = hash(random_state) % len(purple_colors) else: # random_stateがない場合はランダムに選択 idx = random.randint(0, len(purple_colors) - 1) color = purple_colors[idx] return f"rgb({color[0]}, {color[1]}, {color[2]})"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sinjorjob/survey-insight-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server