<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>その他 &#8211; 技術研究Archive</title>
	<atom:link href="https://numaresearch.com/ura-blog/category/other/feed/" rel="self" type="application/rss+xml" />
	<link>https://numaresearch.com/ura-blog</link>
	<description>旧:裏ブログ。 ガジェットレビュー、デスク環境構築、トラブルシューティ ング記録。エンジニアの「思考」と「道具」の保管庫。</description>
	<lastBuildDate>Sun, 05 Apr 2026 14:48:30 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://numaresearch.com/ura-blog/wp-content/uploads/2025/10/cropped-Gemini_Generated_Image_3jloqr3jloqr3jlo-2-32x32.jpg</url>
	<title>その他 &#8211; 技術研究Archive</title>
	<link>https://numaresearch.com/ura-blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>画像挿入時のデフォルトリンク設定を「なし」に強制固定する方法</title>
		<link>https://numaresearch.com/ura-blog/default-image-link-none/</link>
		
		<dc:creator><![CDATA[ぬま畑]]></dc:creator>
		<pubDate>Fri, 03 Apr 2026 06:00:00 +0000</pubDate>
				<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://numaresearch.com/ura-blog/?p=13173</guid>

					<description><![CDATA[■ 目的 記事に画像を挿入した際、デフォルトで画像自体に謎のメディアファイルURLへのリンクが貼られてしまい、読者が誤タップして離脱するのを防ぐ。 ■ 実装コード 現在有効化しているテーマ（または子テーマ）のディレクトリ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>■ 目的</p>



<p>記事に画像を挿入した際、デフォルトで画像自体に謎のメディアファイルURLへのリンクが貼られてしまい、読者が誤タップして離脱するのを防ぐ。</p>



<p>■ 実装コード</p>



<p>現在有効化しているテーマ（または子テーマ）のディレクトリ内にある functions.php の末尾に以下のコードを追記する。</p>



<p>※functions.php は管理画面の「外観」＞「テーマファイルエディター」から編集可能だが、構文エラーによる画面の真っ白化（サイトダウン）を防ぐため、必ずFTPソフトやサーバーのファイルマネージャー経由でバックアップを取ってから追記すること。</p>



<p>パスは /wp-content/themes/使用中のテーマ名/functions.php である。</p>



<pre class="wp-block-code"><code>// 画像挿入時のリンク先デフォルト設定を「なし」にする
add_action( 'after_setup_theme', 'set_default_image_link_none' );
function set_default_image_link_none() {
$image_set = get_option( 'image_default_link_type' );
if ( $image_set !== 'none' ) {
update_option( 'image_default_link_type', 'none' );
}
}</code></pre>



<p>■ 結果</p>



<p>メディアライブラリから画像を挿入する際、リンク先の初期値が常に「なし」に設定される。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【完全自動化】API制限を完全回避！PythonとPlaywrightで作るX・Threads統合型SNS自動投稿システムの構築ガイド</title>
		<link>https://numaresearch.com/ura-blog/python-playwright-sns-auto-post/</link>
		
		<dc:creator><![CDATA[ぬま畑]]></dc:creator>
		<pubDate>Tue, 24 Mar 2026 09:35:10 +0000</pubDate>
				<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://numaresearch.com/ura-blog/?p=13088</guid>

					<description><![CDATA[日々厳しさを増すSNSプラットフォームのAPI制限や、複雑怪奇な仕様変更に頭を抱えてはいないでしょうか。 XのAPI制限によるスクリプトの機能不全は、多くの開発者が直面している現実です。無料で利用できたエンドポイントが突 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-sbd-background-block-title sbd-bg-color sbd-inner-block-init">
<div class="wp-block-sbd-heading"><p>この記事はAIと共同で作成しています。</p></div>
</div>



<p>日々厳しさを増すSNSプラットフォームのAPI制限や、複雑怪奇な仕様変更に頭を抱えてはいないでしょうか。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>XのAPI無料枠が大幅に制限され、従来の自動投稿スクリプトが機能不全に陥った</li>



<li>Threadsへの自動投稿を試みたいが、公式APIの認証フローが複雑すぎて開発が頓挫している</li>



<li>Pythonを用いたブラウザ自動化ツールを構築したが、Windowsのセキュリティに弾かれたり、謎のエラーで停止したりと安定稼働に至らない</li>
</ul>



<p>XのAPI制限によるスクリプトの機能不全は、多くの開発者が直面している現実です。無料で利用できたエンドポイントが突如として有料化されたり、投稿回数に厳しい上限が設けられたりと、プラットフォーム側の都合でシステムが停止するリスクが常に付きまといます。</p>



<p>Threadsの自動投稿においても同様です。APIの仕様が頻繁にアップデートされる過渡期においては、公式のドキュメントを追従するだけでも多大なリソースを消費します。</p>



<p>さらに、実行環境側（Windows OSなど）の強固なセキュリティ機能や、ブラウザ自動化ツール特有の環境依存エラー（アクセス拒否やプロセスの暴走）によって、ローカル環境での定期実行が阻まれるケースも後を絶ちません。</p>



<p>結論から申し上げます。他者が提供する<span class="sbd-text-red"><span class="sbd-text-bg-yellow">APIの仕様変更に怯える日々は、今日で終わりにしましょう</span></span>。</p>



<p>APIに一切依存せず、Playwrightを用いた直接的なDOM（Webページの要素）操作と、堅牢な3層アーキテクチャを組み合わせることで、完全放置による安定したSNS自動投稿システムは確実に構築可能です。</p>



<p>システムの各フェーズである【データ生成】【データ統制】【投稿実行】を独立させることでリスクを分散させています。</p>



<p>そして、OSやプラットフォームの隠し仕様に対しては、その仕様を完全にトレースする論理的なロジックを自前で実装します。これにより、外部要因によるシステムのクラッシュを完全に防ぐことができます。</p>



<p>本記事では、複数ブログの記事を要約し、XとThreadsへ投下し続ける統合型自動SNSディストリビューションシステム【FREEDOM】の構築プロセスと、その過程で直面した致命的エラーの解決ロジックをすべて公開いたします。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>統合型自動SNSシステム【FREEDOM】の3層アーキテクチャ設計</li>



<li>Xの特殊なURL文字数換算仕様の解析とトリミング処理</li>



<li>WindowsのSmart App Controlによる実行ブロックの合法的な回避手法</li>



<li>Playwright環境におけるアクセス拒否（0x5）エラーとゾンビプロセスの完全排除</li>
</ul>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<a class="twitter-timeline" data-width="500" data-height="750" data-dnt="true" href="https://twitter.com/YNumahata?ref_src=twsrc%5Etfw">Tweets by YNumahata</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>



<p>上記アカウントを見ていただけば一目瞭然です。</p>



<p>統合型自動SNSシステムの3層アーキテクチャ設計では、なぜ処理を分割すべきなのかというインフラ設計の基礎を解説します。</p>



<p>ただ、すみません。今回はコードをここに貼り付けるということはしません。ですが、ぶっちゃけAIに聞けば余裕で構築できますし、なんならclaude codeですぱっと構築できたりします。</p>



<p>今回渡しの場合はGeminiを使用しましたが、『こういう事ができるよ』というベースで初心者の方にお伝えするというものなのでその点はご了承ください。</p>



<p>コードを見たいという場合は、コメント等で教えていただければお伝えします。</p>



<p>さて、ここではXのURL文字数換算仕様の解析では、文字数制限オーバーというエラーをPython側でどう論理的に防ぐかを解説します。</p>



<p>WindowsのSmart App Control回避では、セキュリティレベルを一切下げることなく、OSの信頼プロセスを活用してバッチ処理を実行するテクニックを公開します。</p>



<p>アクセス拒否エラーとゾンビプロセスの排除では、自動化ツールを長期運用する際に必ず直面するメモリの圧迫と権限エラーを、インフラエンジニアの視点で根絶する方法をお伝えします。</p>



<p>この記事を最後までお読みいただくことで、単なるコピペスクリプトの作成にとどまらない、本質的で論理的なインフラ設計の思考法と、安定稼働を約束するトラブルシューティングのノウハウを習得できます。</p>



<h2 class="wp-block-heading">統合型自動SNS投稿システムの全体アーキテクチャ</h2>



<p>システムの安定稼働において最も忌むべきものは、単一障害点（SPOF：Single Point of Failure）の存在です。</p>



<p>初心者がシステムを組む際、データの取得からテキストの生成、スケジューリング、そして実際の投稿処理に至るまで、すべてを1つのPythonファイルに詰め込む設計をしがちです。しかし、この設計はどれか1つの処理がエラーを起こした瞬間（例えばネットワークの瞬断やAPIのタイムアウト）に、システム全体が沈黙するという非常に脆弱な構造です。</p>



<p>この致命的な問題を解決するため、本システム【FREEDOM】では、システム全体の工程を完全に分離・独立させた3層のアーキテクチャ（Layer 1〜3）を採用しています。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>Layer 1（製造）：各WordPressブログに配置したGoogle Apps Script（GAS）</li>



<li>Layer 2（統制）：中央に配置したマスターデータベース（GASとスプレッドシート）</li>



<li>Layer 3（実行）：ローカルのWindows 11稼働専用機（PythonとPlaywright）</li>
</ul>



<p>Layer 1は、テキストデータの生成のみに責任を持ちます。Layer 2は、データの保管と適切な順序での受け渡しのみを担当します。そしてLayer 3は、受け取ったデータを元にブラウザを操作して投稿することだけに特化しています。</p>



<p>これら3つのレイヤーがどのように独立して稼働し、一つの巨大な自動化ミッションを完遂しているのか。各層の論理的な役割と実装の意図を詳細に解説いたします。</p>



<h3 class="wp-block-heading">Layer 1（製造）：各WordPressブログにおけるコンテンツの自動生成</h3>



<p>第1の層は、各WordPressブログに配置されたスレーブ（従属機）としてのGoogle Apps Script（GAS）です。このレイヤーの唯一の目的は、自サイトの最新記事を検知し、SNSへの投稿に最適化された魅力的なテキストデータを作成してデータベースへ送ることです。</p>



<p>各ブログに仕込まれたGASは、定期タイマーによって自動的に起動し、サイトのRSSフィードから最新記事のタイトル、URL、抜粋データを取得します。</p>



<p>ここで重要なのは、取得した文字列をそのままSNSに流し込まないことです。システムは取得したデータをGoogleの高性能生成AIであるGemini APIへ送信し、プラットフォームごとの文化に合わせた2種類のテキストを自動生成させます。</p>



<p>プロンプトによる厳格な制御を用いて、X用には【短文かつハッシュタグを含むテキスト】を生成させ、Threads用には【長文でハッシュタグを含まない、対話的なテキスト】を生成させます。</p>



<p>XとThreadsでは、ユーザーが好むフォーマットやタイムラインの雰囲気が明確に異なります。同一のテキストを機械的に使い回すことは、マーケティングの観点からもエンゲージメントの低下を招く悪手です。生成された2種類の専用テキストとメタデータ（URLなど）は、JSON形式という扱いやすいデータ形式にパッケージングされ、次の層であるマスターデータベースへと送信されます。</p>



<h3 class="wp-block-heading">Layer 2（統制）：中央マスターDBとランダム抽出ロジックによるサイロ化の防止</h3>



<p>第2の層は、各ブログから送られてきたテキストデータを受け取り、一時的にストックし、実行部隊の要求に応じて的確に払い出しを行う中央データベースです。ここでもGASとGoogleスプレッドシートを組み合わせることで、完全無料のAPIエンドポイントを構築しています。</p>



<p>各ブログから送信されたデータは、スプレッドシート上に【未投稿】というステータスでどんどん蓄積されていきます。開発初期の設計では、Layer 3（実行部隊）からデータの要求があった際、スプレッドシートの上から順に（つまり古いものから順に）データを渡すという極めて単純な仕様にしていました。</p>



<p>しかし、テスト運用を行う中で、この単純な仕様が運用上の致命的な欠陥を生み出すことが判明しました。例えば、特定のブログが1日の間に立て続けに3本の記事を更新した場合、マスターデータベースにはそのブログのデータが連続して3つストックされます。</p>



<p>その結果、SNSのタイムライン上には、同じジャンル、同じブログの投稿ばかりが連続して投下される【ジャンルのサイロ化（偏り）】が発生してしまったのです。これではフォロワーにスパムボットのような印象を与えかねません。</p>



<p>この問題を解決するため、API（doGet関数）のロジックを根本から書き換えました。</p>



<p>単に上からデータを取得するのではなく、ステータスが【未投稿】となっている全ての配列データを一度取得し、その中から【完全にランダムで1件を抽出】して払い出すロジックへと改修しました。</p>



<p>完全にランダムで1件を抽出することにより、複数のブログから集まった技術系、ゲーム系、ガジェット系といった多様なジャンルが完璧にミキシングされます。結果として、フォロワーを飽きさせない、人間が手動で投稿しているかのような自然なタイムラインの形成を実現しました。</p>



<h3 class="wp-block-heading">Layer 3（実行）：ローカル専用機でのPythonとPlaywrightによる実行</h3>



<p>第3の層は、ローカル環境に設置されたWindows 11専用機で稼働する、PythonとPlaywrightを用いた実行部隊です。このレイヤーの目的は、クラウドサーバーやVPS特有のデータセンターIP帯による制限（シャドウバンやボット判定）を回避し、一般家庭のプロバイダ回線を経由して、人間のブラウザ操作と見分けのつかない挙動でSNSへの投稿を完遂することです。</p>



<p>スケジューリング（投稿間隔）の設計においても、細心の注意を払っています。毎日決まった時刻や、きっちり2時間おきといった機械的な一定間隔の投稿は、SNSのスパム検知アルゴリズムに捕捉されるリスクを跳ね上げます。</p>



<p>そのため、Pythonスクリプトは毎時0分に起動し、乱数を用いて【その1時間の間に何回投稿するか】と【何分に投稿するか】を都度完全にランダムで算出する高度なロジックを搭載しています。これにより、人間の気まぐれなログイン間隔を完璧に模倣します。</p>



<p>算出した予定時刻に到達すると、Pythonは直ちにLayer 2のマスターデータベースへアクセスしてテキストデータを引き抜きます。その後、Playwrightを用いてブラウザを起動し、テキストボックスへの入力から投稿ボタンのクリックまで、実際の画面上でDOMを操作してXとThreadsへの自動投稿を行います。</p>



<p>公式APIの理不尽な制限や、頻繁に変わる複雑な認証仕様を一切無視し、フロントエンドから物理的にキーボード入力をシミュレートするこの手法は、SNS側のユーザーインターフェースが根本的に変更されない限り機能し続ける、極めて堅牢なアプローチです。</p>



<h2 class="wp-block-heading">システム稼働を阻む4つの致命的エラーと突破の論理</h2>



<p>アーキテクチャの設計がいかに完璧であっても、実際の運用環境ではプラットフォームの理不尽な仕様や、OS特有の予期せぬエラーが必ず牙を剥きます。</p>



<p>本システム【FREEDOM】の開発とテスト運用中、インフラの安定稼働を根底から脅かす4つの致命的な壁に直面しました。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>XのURL文字数換算仕様と過剰防衛トリミング</li>



<li>WindowsのSmart App Controlによる実行ファイルのブロック</li>



<li>PlaywrightとChromeのパス誤認によるアクセス拒否（0x5エラー）</li>



<li>沈黙するコンソールによるシステムのブラックボックス化</li>
</ul>



<p>システムエンジニアたるもの、これらのエラーに対して再起動で誤魔化すような場当たり的な対処をしてはなりません。原因をファクトに基づいて特定し、論理的かつ恒久的な解決策をどのように実装したのかを、初心者の方にも分かりやすく解説します。</p>



<h3 class="wp-block-heading">XのURL文字数換算仕様と過剰防衛トリミング</h3>



<p>最初に立ち塞がった壁は、Xへの投稿処理時に発生した文字数制限のエラーです。テキストを作成する際、システムが140文字（全角）の制限を大幅に超過したと誤認し、重要なハッシュタグや文章の後半部分を過剰に切り落としてしまう（トリミングしてしまう）バグが発生しました。</p>



<p>この原因は、Xプラットフォーム特有の内部仕様と、プログラミング言語（Python）の標準的な文字数カウントロジックとの間に存在する明確なギャップにあります。</p>



<p>通常、Pythonの<code>len()</code>関数などを使用して文字数をカウントすると、65文字ある長いURLは、馬鹿正直にそのまま65文字としてカウントされます。しかし、Xの内部仕様では異なります。Xはセキュリティチェックやアクセス解析のため、入力されたどのような長さのURLであっても、投稿時には公式の短縮URL（t.co）に自動で変換する仕組みを持っています。</p>



<p>この短縮URLは、元の長さに関わらず一律で【半角23文字（全角換算で11.5文字分）】として扱われます。</p>



<p>つまり、65文字のURLを含んで合計150文字になっているテキストは、Xの画面上では「URL（11.5文字分）＋その他のテキスト（85文字）」となり、合計100文字未満で余裕で制限内に収まっています。しかし、Python側は「150文字だから制限の140文字を超えている！」と判定し、テキストを削り落としていたのです。</p>



<p>この問題を恒久的に解決するため、Pythonの投稿準備処理内に、Xの内部仕様と全く同じ計算を行うカスタム関数（enforce_length_limit）を実装しました。</p>



<p>具体的には、正規表現を用いてテキスト内に含まれるURLを抽出し、その実際の文字数を全体のカウントからマイナスした上で、強制的に全角12文字分を加算するアルゴリズムです。これにより、長いURLを含む投稿であっても寸分違わぬ正確な文字数計算が可能となり、テキストの欠損を完全に防ぐ論理的なトリミング防壁が完成しました。</p>



<h3 class="wp-block-heading">WindowsのSmart App Controlによる実行ファイルのブロック</h3>



<p>第2の壁は、実行環境であるWindows 11 OS自体の過剰なセキュリティ防壁です。</p>



<p>作成したPythonスクリプトをタスクスケジューラなどで容易に実行・管理するため、初めはPyInstallerを用いてexeファイル（実行可能ファイル）化したり、batファイル（バッチファイル）化したりすることを試みました。しかし、これらのファイルを実行しようとすると、Windowsの高度なセキュリティ機能であるSmart App ControlやDevice Guardによって無慈悲に実行がブロックされてしまいました。</p>



<p>ブロックされる理由は明確です。個人が作成した実行ファイルには、Microsoftや信頼できる認証局が発行する【デジタル署名】が存在しないため、OS側が「出所不明の危険なプログラムである」と判定してしまうからです。</p>



<p>ここで、「スクリプトを動かすためにWindowsのSmart App Controlを無効化する」あるいは「セキュリティの保護レベルを下げる」という選択をするのは、インフラを構築するエンジニアとして下策の極みです。全体のセキュリティを犠牲にして部分的な利便性を取ることは絶対に避けなければなりません。</p>



<p>そこで、セキュリティ設定を一切変更することなく、この厳格な検閲を合法的にすり抜けるため、Windows標準の機能である【ショートカット（.lnkファイル）】を活用する手法を採用しました。具体的には、スクリプトへのショートカットを作成し、そのプロパティのリンク先（ターゲット）を以下のように指定します。</p>



<p><code>cmd.exe /k python C:\path\to\auto_post.py</code></p>



<p>この設計の論理的な肝は、OSが実行ファイルとして認識する対象をすり替えることです。OSがチェックするのは、署名のない独自のexeファイルではなく、Windowsがデフォルトで完全に信頼しているコマンドプロンプト（<code>cmd.exe</code>）になります。</p>



<p>OSから見れば「信頼できるコマンドプロンプトが起動し、その中でPythonコマンドを実行しているだけ」という極めて正常なプロセスに見えます。OSの信頼プロセスをいわば裏口として適切に利用することで、セキュリティの網を一切鳴らすことなく、スクリプトの完全な定期実行を確立しました。</p>



<h3 class="wp-block-heading">PlaywrightとChromeのパス誤認によるアクセス拒否（0x5）</h3>



<p>第3の壁は、Playwright実行時に発生した致命的なアクセス拒否エラー（エラーコード：0x5）です。</p>



<p>自動投稿を行う際、毎回ログインからやり直していては効率が悪く、不審なログインとしてアカウントがロックされる危険性があります。そのため、ブラウザのセッション情報（ログイン状態やCookie）を保持するディレクトリ（プロファイル保存先）を指定する必要がありますが、この指定を行った途端にシステムがクラッシュしました。</p>



<p>原因は、プロファイルの保存先を<code>./chrome_profile</code>のように【相対パス】で指定していたことにあります。</p>



<p>タスクスケジューラや先述のショートカットを経由してスクリプトが呼び出された際、システムが認識するカレントディレクトリ（実行時の基準となる作業フォルダ）は、スクリプトが置いてある場所ではなく、<code>C:\Windows\System32</code>などのシステム領域になってしまうことが多々あります。</p>



<p>その結果、PlaywrightはWindowsの心臓部であるSystem32フォルダの直下に<code>chrome_profile</code>というフォルダを作成し、データの書き込みを行おうとパニックを起こします。当然、そのような場所への書き込みは管理者権限が必要なため、OSのUAC（ユーザーアカウント制御）によって権限エラー、すなわち【アクセス拒否（0x5）】として弾かれていたのです。</p>



<p>この問題の解決策は、実行方法に依存しない【絶対パス】での厳格なロックです。スクリプト内でディレクトリを指定する際、<code>r"C:\FREEDOM_System\chrome_profile"</code>のようにドライブ名から始まる絶対パスでハードコード（または環境設定ファイルから読み込み）を行い、データの書き込み先を物理的に固定しました。</p>



<p>さらに、アクセス拒否が起きる別の要因として、前回の実行時に何らかの理由でPlaywrightがクラッシュし、バックグラウンドに見えないChromeのプロセス（ゾンビプロセス）が残存したままファイルをロックしているケースもありました。</p>



<p>このゾンビプロセスを完全に排除するため、Playwrightのプロセスを起動する直前に、OSのコマンドを用いて既存のChromeプロセスを強制的に終了させる（<code>taskkill /F /IM chrome.exe /T</code> 相当の処理）クリーンアップロジックを実装しました。これにより、環境依存の不安定要素を根絶しています。</p>



<h3 class="wp-block-heading">沈黙するコンソールによるシステムのブラックボックス化</h3>



<p>最後の壁は、プログラミングコードのエラーではなく、運用上のシステム設計に関わる重要な問題です。それは【可視性の欠如】です。</p>



<p>Layer 3の実行システムは、毎時0分にランダムなスケジュールを算出し、予定時刻にひっそりと投稿を行った後、次の時間帯のスケジュール計算まで完全に沈黙します。コマンドプロンプトのコンソール画面には何も表示されず、黒い画面がただ置かれているだけになります。</p>



<p>管理者としては、この黒い画面を見たときに「システムは正常に時間を待っている（待機中）のか」、それとも「内部で無限ループに陥ってフリーズしている（停止中）のか」を外から判断する術がありません。</p>



<p>インフラストラクチャにおいて、内部の状態がどうなっているのか把握できないブラックボックス化は、運用者に多大なストレスを与える最大の運用リスクです。</p>



<p>この不安を払拭するため、ロギングとコンソール出力の設計を大幅に見直しました。投稿処理が完了した直後、または毎時0分の計算処理が完了した直後に、以下のデータをコンソール画面へ明示的に出力するロジックを追記しました。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>現在の時刻とシステムのステータス（待機中であるか、実行中であるかの明示）</li>



<li>その1時間内において算出された「残りの予定投稿回数」</li>



<li>次の投稿が行われる「着弾予定時刻（〇時〇分）」</li>
</ul>



<p>ただ待機機能（<code>time.sleep</code>）を使うだけでなく、システムが今何を考え、次にいつ動く予定なのかを常にテキストとして可視化することで、システム監視における不要な不安と不透明性を完全に排除しました。ちょっとしたユーモアを交えたログメッセージを表示させることで、開発者自身のモチベーション維持にも繋がっています。</p>



<h2 class="wp-block-heading">まとめ：妥協なき設計だけが真の自動化を実現する</h2>



<p>APIの仕様変更に振り回されず、OSのセキュリティを低下させることなく、完全放置で動作し続ける自動化システムを構築するためには、単にネットに落ちている表面的なコードを繋ぎ合わせるだけでは不十分です。</p>



<p>本システム【FREEDOM】の構築プロセスで示した通り、発生しうる最悪のシナリオ（パスの誤認、プロセスの暴走、仕様のギャップ）をあらかじめ想定し、それらを徹底した論理によって一つずつ潰していくインフラ設計のアプローチが必須となります。</p>



<p>他者が用意した環境やデフォルトの設定に盲従することは、運用における大きな脆弱性に直結します。妥協のないアーキテクチャ設計と、ファクトに基づくデバッグの徹底こそが、真の自動化と長期的なシステムの安定稼働をもたらす唯一の解であると断言します。</p>



<p>この記事が、自動化の壁に挑む皆様の設計の一助となれば幸いです。</p>



<p>それでは最後まで御覧いただきありがとうございました！ﾉｼ</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【脱GitHub Actions】XserverとGASでTDR待ち時間を正確に記録する構築ログ</title>
		<link>https://numaresearch.com/ura-blog/tdr-wait-time-gas-xserver/</link>
		
		<dc:creator><![CDATA[ぬま畑]]></dc:creator>
		<pubDate>Wed, 18 Feb 2026 16:25:00 +0000</pubDate>
				<category><![CDATA[PC・技術ハック]]></category>
		<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://numaresearch.com/ura-blog/?p=13054</guid>

					<description><![CDATA[本稿は、東京ディズニーリゾート（TDR）の待ち時間データを、15分間隔かつ秒単位の精度で収集・蓄積するデータパイプラインの構築記録です。 以前、GitHub ActionsとGAS（Google Apps Script） [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>本稿は、<strong><span class="sbd-text-bg-yellow">東京ディズニーリゾート（TDR）の待ち時間データ</span></strong>を、<strong><span class="sbd-text-red">15分間隔かつ秒単位の精度で収集・蓄積するデータパイプラインの構築記録</span></strong>です。</p>



<p>以前、GitHub ActionsとGAS（Google Apps Script）を用いたサーバーレス構成で運用を試みましたが、<strong><span class="sbd-text-bg-yellow">「プラットフォーム依存による実行遅延（5分～30分の不可避なラグ）」と「リソース共有による実行スキップ」</span></strong>という構造的な欠陥に直面しました。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-archive wp-block-embed-archive"><div class="wp-block-embed__wrapper">
<div class="p-blogcard c-hover-opacity p-blogcard-1"><a href="https://numaresearch.com/ura-blog/tdr-wait-time-automation/" class="p-blogcard__img-area"><img fetchpriority="high" decoding="async" width="320" height="180" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/02/image-320x180.jpg" class="p-blog-card__thumb wp-post-image" alt="" srcset="https://numaresearch.com/ura-blog/wp-content/uploads/2026/02/image-320x180.jpg 320w, https://numaresearch.com/ura-blog/wp-content/uploads/2026/02/image-224x126.jpg 224w" sizes="(max-width: 320px) 100vw, 320px" /></a><a href="https://numaresearch.com/ura-blog/tdr-wait-time-automation/" class="p-blogcard__title-area">TDR待ち時間自動収集システムの構築手順｜GitHubとGASで資産化する方法</a><a href="https://numaresearch.com/ura-blog/tdr-wait-time-automation/" class="p-blogcard__excerpt-area">ディズニーパークの混雑傾向を自分で分析したいが、手動での記録には限界がある



既存の待ち時間サイトが閉鎖されるリスク</a><div class="p-blogcard__btn-area"><a href="https://numaresearch.com/ura-blog/tdr-wait-time-automation/" class="p-blogcard__btn c-btn">記事を読む</a></div></div>
</div></figure>



<p>データの鮮度が価値そのものであるリアルタイム分析において、制御不能な遅延は致命的です。 そこで私は、利便性を優先したGitHub Actionsを撤廃し、<span class="sbd-text-red"><span class="sbd-text-bg-yellow"><strong>Xserver（Cron/Node.js）とGASを組み合わせた「オンプレミス回帰」とも言える堅牢な自律分散システム</strong>へと移行</span></span>しました。</p>



<p>本記事では、以下の技術的課題をどのように解決し、月間数万レコードのデータを安定稼働させているか、その設計思想と実装の全容を公開します。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>完全制御：</strong>Cronによる秒単位の実行スケジューリング</li>



<li><strong>データ整合性：</strong>JST（日本標準時）の厳密な管理と重複排除</li>



<li><strong>耐障害性：</strong>API制限（429 Error）を考慮した指数バックオフの実装</li>
</ul>



<p>単なるスクレイピングの手順書としてではなく、<strong>「信頼性の高いデータ収集基盤をどう設計すべきか」</strong>というエンジニアリングのケーススタディとしてご覧ください。</p>



<h2 class="wp-block-heading">GitHub Actionsをスクレイピングに使ってはいけない理由</h2>



<p>なぜ、無料で手軽なGitHub Actionsを捨てる必要があるのでしょうか。その理由は、以下の2点に集約されます。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>実行時刻の不透明な遅延</strong></li>



<li><strong>リソース共有による実行スキップ</strong></li>
</ul>



<p>GitHub Actionsのスケジュール実行は「ベストエフォート」であり、起動時刻が保証されません。10時00分に設定しても、実際には10時15分に開始されることが頻繁にあり、この15分のズレはデータの価値をゼロにします。（検証した結果、1時間後に実行されることもありました…）</p>



<p>また、混雑時には実行待機やスキップが発生し、ログすら残らず処理が消滅します。原因の切り分けが不可能になることは、長期運用において致命的なリスクとなるため、GitHub Actionsの使用を撤廃したと言うわけです。</p>



<h2 class="wp-block-heading">XserverとGASによるシステム構成</h2>



<p>データの正確性と連続性を高めるため、以下の役割分担でシステムを再構築しました。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>実行エンジン：Xserver (Node.js)</strong></li>



<li><strong>データベース：GAS + Google Spread Sheets</strong></li>
</ul>



<p>Xserver側では、Cronによる秒単位の定期実行、JST（日本標準時）の管理、リトライ処理を担当させます。一方、GAS側にはデータの受信、マスタデータとの照合（名寄せ）、および「蓄積ログ」の保存を担当させます。</p>



<p>この構成により、実行の正確さとデータの扱いやすさを両立させました。</p>



<h2 class="wp-block-heading">Phase 1：GAS側（受信・蓄積エンジン）の構築</h2>



<p>まず、データを受け取って保存する「データベース部分」を構築します。ここでは「蓄積ログ」と、英語名を日本語に変換するための「施設マスタ」の2つを用意します。</p>



<h3 class="wp-block-heading">1. スプレッドシートの準備</h3>



<p>新規スプレッドシートを作成し、以下の2つのシートを用意してください。</p>



<h4 class="wp-block-heading">① シート名：「蓄積ログ」</h4>



<p>収集したデータをひたすら溜めていくメインのシート（蓄積ログシート）です。1行目に以下のヘッダーを設定します。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>A列：日付</strong></li>



<li><strong>B列</strong>：<strong>時間</strong></li>



<li><strong>C列：曜日</strong></li>



<li><strong>D列：祝日</strong></li>



<li><strong>E列：パーク</strong></li>



<li><strong>F列：アトラクション名</strong></li>



<li><strong>G列：カテゴリ</strong></li>



<li><strong>H列：エリア</strong></li>



<li><strong>I列：DPA</strong></li>



<li><strong>J列：待ち時間 </strong></li>



<li><strong>K列：元時刻</strong></li>



<li><strong>L列：RunID</strong></li>
</ul>



<h4 class="wp-block-heading">② シート名：「施設マスタ」</h4>



<p>APIから来る英語名を、日本語名やエリア情報に変換するための辞書シート（マスタシート）です。ヘッダーは以下のように設定します。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>A列：英語名</strong></li>



<li><strong>B列：日本語</strong></li>



<li><strong>C列：カテゴリ</strong></li>



<li><strong>D列：エリア</strong></li>



<li><strong>E列：DPA</strong></li>
</ul>



<p>このマスタシートに行を追加していけば、コードを触らずに新アトラクションに対応できます。</p>



<h3 class="wp-block-heading">2. GASコードの実装 (doPost)</h3>



<p>Xserverからのデータを受け取り、マスタシートを参照して日本語化し、ログに追記するコードです。</p>



<pre class="wp-block-code"><code>/**
 * TDRデータ受信サーバー (doPost)
 * 生データを受け取り、日時分解・マスタ結合を行って蓄積ログへ保存する
 */
function doPost(e) {
  const lock = LockService.getScriptLock();
  if (!lock.tryLock(10000)) return ContentService.createTextOutput("Busy");

  try {
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    const logSheet = ss.getSheetByName("蓄積ログ");
    const masterSheet = ss.getSheetByName("施設マスタ");
    
    // --- 1. マスタデータの読み込み (Map化) ---
    // A列:英語, B:日本語, C:カテゴリ, D:エリア, E:DPA
    const masterValues = masterSheet.getDataRange().getValues();
    const masterMap = new Map();
    // ヘッダー行(0)をスキップ
    for (let i = 1; i &lt; masterValues.length; i++) {
      masterMap.set(masterValues&#91;i]&#91;0], {
        jp: masterValues&#91;i]&#91;1],
        category: masterValues&#91;i]&#91;2],
        area: masterValues&#91;i]&#91;3],
        dpa: masterValues&#91;i]&#91;4]
      });
    }

    // --- 2. 受信データのパース ---
    const rawData = JSON.parse(e.postData.contents);
    if (!rawData || rawData.length === 0) return ContentService.createTextOutput("No Data");

    // --- 3. 重複チェック (RunID) ---
    const newRunId = rawData&#91;0].run_id.toString();
    const lastRow = logSheet.getLastRow();
    if (lastRow > 1) {
      // L列(12列目)がRunID
      const lastRunId = logSheet.getRange(lastRow, 12).getValue().toString();
      if (lastRunId === newRunId) return ContentService.createTextOutput("Skipped");
    }

    // --- 4. 日時・祝日判定の準備 ---
    // Xserverから送られてくる updateTime (例: "2026/02/19 12:00:00") を解析
    const updateTimeStr = rawData&#91;0].updateTime; 
    const dateObj = new Date(updateTimeStr);
    
    // 日付 (YYYY/MM/DD)
    const dateStr = Utilities.formatDate(dateObj, "Asia/Tokyo", "yyyy/MM/dd");
    // 時間 (HH:mm)
    const timeStr = Utilities.formatDate(dateObj, "Asia/Tokyo", "HH:mm");
    // 曜日
    const weekDay = &#91;"日", "月", "火", "水", "木", "金", "土"]&#91;dateObj.getDay()];
    // 祝日判定 (Googleカレンダー利用)
    const calendarId = 'ja.japanese#holiday@group.v.calendar.google.com';
    const holidays = CalendarApp.getCalendarById(calendarId).getEventsForDay(dateObj);
    const isHoliday = (holidays.length > 0) ? "祝日" : "平日"; // 土日の場合も"平日"表記になるため、必要なら要調整

    // --- 5. データ変換 (マスタ結合 &amp; A-L列生成) ---
    const rows = rawData.map(d => {
      // マスタ取得（なければ英語名のまま・不明扱い）
      const info = masterMap.get(d.name) || { 
        jp: d.name, category: "-", area: "-", dpa: "-" 
      };

      // 待ち時間の処理（CLOSE等は -1 になっているので文字に直すならここ。今回は数値をそのまま入れる）
      const waitVal = (d.status === "OPERATING") ? d.waitTime : -1; 
      // ※もしログ上で「休止」と文字で出したい場合は上記を書き換える

      return &#91;
        dateStr,        // A: 日付
        timeStr,        // B: 時間
        weekDay,        // C: 曜日
        isHoliday,      // D: 祝日
        d.park,         // E: パーク
        info.jp,        // F: アトラクション名
        info.category,  // G: カテゴリ
        info.area,      // H: エリア
        info.dpa,       // I: DPA
        waitVal,        // J: 待ち時間
        d.updateTime,   // K: 元時刻
        d.run_id        // L: RunID
      ];
    });

    // --- 6. 蓄積ログへの追記 ---
    logSheet.getRange(lastRow + 1, 1, rows.length, 12).setValues(rows);

    return ContentService.createTextOutput("Success");

  } catch (err) {
    return ContentService.createTextOutput("Error: " + err.toString());
  } finally {
    lock.releaseLock();
  }
}</code></pre>



<h3 class="wp-block-heading">3. デプロイとURLの発行</h3>



<p>Xserverからのアクセスを許可するため、以下の設定でデプロイを行います。</p>



<p>画面右上の [デプロイ] > [新しいデプロイ] をクリック。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>種類の選択：</strong>ウェブアプリ</li>



<li><strong>次のユーザーとして実行：</strong>「自分 (Me)」</li>



<li><strong>アクセスできるユーザー：</strong>全員 (Anyone)<strong>※最重要</strong></li>
</ul>



<p>発行されたURLは、次のフェーズで使用します。（これが後の工程で使用する「<strong>gasUrl</strong>」に設定するURLとなります。）</p>



<h2 class="wp-block-heading">Phase 2：Xserver側（実行環境）の構築</h2>



<p>WordPress等が稼働している公開領域を汚染しないよう、隔離されたディレクトリに実行環境を作ります。</p>



<p>まずは接続する設定をXサーバーの管理画面で行います。</p>



<h3 class="wp-block-heading">準備</h3>



<p>まずは準備が必要です。</p>



<ol start="1" class="wp-block-list is-style-sbd-border-orange">
<li>[サーバーパネル] ＞ [SSH設定] ＞ [ONにする]。</li>



<li>[公開鍵認証用鍵ペア生成] ＞ パスフレーズを入力し [生成する] をクリック。</li>
</ol>



<p><strong>ローカル（PC）での配置</strong>：</p>



<p><code>.ssh</code> ディレクトリへ移動し、鍵の権限を厳格に設定（chmod 600）。</p>



<p><strong>SSH接続コマンド</strong>：</p>



<pre class="wp-block-code"><code>ssh -i ~/.ssh/〇〇.key 〇〇@〇〇.xsrv.jp -p 10022</code></pre>



<p>※〇〇サーバー番号、ポート番号はデフォルトの22ではなく、Xserver指定の 10022 を使用します。</p>



<h3 class="wp-block-heading">1. SSH接続とNode.jsの導入</h3>



<p>セキュリティを担保するため、公開鍵認証にてSSH接続を行います。接続後、バージョン管理ツール <code>nodebrew</code> を使用して Node.js（v18系推奨）をインストールしてください。</p>



<h3 class="wp-block-heading">2. プロジェクトディレクトリの作成</h3>



<p>ホームディレクトリ直下に隠しディレクトリを作成し、プロジェクトを初期化します。</p>



<pre class="wp-block-code"><code>mkdir -p ~/.tdr_system/fetcher
cd ~/.tdr_system/fetcher
npm init -y
npm install node-fetch@2</code></pre>



<h2 class="wp-block-heading">Phase 3：収集ロジックの実装 (index.js)</h2>



<p>タイムゾーン（JST）を厳密に管理し、API制限対策のリトライ機能を搭載したエンジンを実装します。このフェーズでの重要なポイントは以下の3点です。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>JST時刻の厳密管理</strong></li>



<li><strong>指数バックオフ（リトライ）</strong></li>



<li><strong>直接ファイルロギング</strong></li>
</ul>



<p>サーバーの時刻設定に依存せず、<code>Intl.DateTimeFormat</code> で日本時間を強制取得します。また、通信エラー時に即時終了せず、間隔を空けて再試行することで欠測を防ぎます。ログは標準出力ではなく、ファイルへ直接書き込むことでバッファ消失を防ぎます。</p>



<pre class="wp-block-code"><code>/**
 * TDRデータ収集・送信エンジン
 */
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');

// Phase 1で発行したGASのURL
const gasUrl = 'https://script.google.com/macros/s/xxxxxxxxxxxxxxxxx/exec';

const logPath = path.join(__dirname, 'execution.log');
const writeLog = (msg) => {
    const now = new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
    fs.appendFileSync(logPath, `&#91;${now}] ${msg}\n`);
};

(async () => {
    const now = new Date();
    const jstFormatter = new Intl.DateTimeFormat('ja-JP', {
        timeZone: 'Asia/Tokyo',
        year: 'numeric', month: '2-digit', day: '2-digit',
        hour: 'numeric', minute: '2-digit', second: '2-digit',
        hour12: false
    });
    
    const parts = jstFormatter.formatToParts(now);
    const p = parts.reduce((acc, part) => { acc&#91;part.type] = part.value; return acc; }, {});
    
    const timestamp = `${p.year}/${p.month}/${p.day} ${p.hour}:${p.minute}:${p.second}`;
    const hour = parseInt(p.hour);
    const min = parseInt(p.minute);

    writeLog(`Check: ${timestamp} (H:${hour} M:${min})`);

    // 21:01〜07:59は実行停止
    if ((hour === 21 &amp;&amp; min > 0) || hour > 21 || hour &lt; 8) {
        writeLog("Operation out of hours. Process skipped.");
        process.exit(0);
    }

    const fetchWithRetry = async (url, options = {}, retries = 3) => {
        for (let i = 0; i &lt; retries; i++) {
            try {
                const res = await fetch(url, options);
                if (res.ok) return res;
                writeLog(`HTTP Error: ${res.status} (Attempt ${i + 1})`);
            } catch (err) {
                writeLog(`Network Error: ${err.message} (Attempt ${i + 1})`);
            }
            if (i &lt; retries - 1) await new Promise(r => setTimeout(r, 5000 * (i + 1)));
        }
        throw new Error(`Max retries reached: ${url}`);
    };

    try {
        const destRes = await fetchWithRetry('https://api.themeparks.wiki/v1/destinations');
        const destData = await destRes.json();
        const resort = destData.destinations.find(d => d.name.toLowerCase().includes('tokyo'));

        const childrenRes = await fetchWithRetry(`https://api.themeparks.wiki/v1/entity/${resort.id}/children`);
        const childrenData = await childrenRes.json();
        const targetParks = childrenData.children.filter(c => 
            c.name.toLowerCase().includes('disneyland') || c.name.toLowerCase().includes('disneysea')
        );

        const runId = now.getTime().toString(); 
        let allAttractions = &#91;];

        for (const park of targetParks) {
            const liveRes = await fetchWithRetry(`https://api.themeparks.wiki/v1/entity/${park.id}/live`);
            const liveData = await liveRes.json();
            const parkType = park.name.toLowerCase().includes('disneyland') ? 'TDL' : 'TDS';

            const attractions = liveData.liveData.map(ride => ({
                park: parkType,
                name: ride.name,
                waitTime: (ride.queue &amp;&amp; ride.queue.STANDBY) ? (ride.queue.STANDBY.waitTime || 0) : -1,
                status: ride.status,
                updateTime: timestamp,
                run_id: runId
            }));
            allAttractions = allAttractions.concat(attractions);
        }

        writeLog(`Sending ${allAttractions.length} records to GAS...`);
        const response = await fetchWithRetry(gasUrl, {
            method: 'POST',
            body: JSON.stringify(allAttractions),
            headers: { 'Content-Type': 'application/json' }
        });

        writeLog(`GAS Response: ${await response.text()}`);

    } catch (e) {
        writeLog(`CRITICAL: ${e.message}\n${e.stack}`);
        process.exit(1);
    }
})();</code></pre>



<h2 class="wp-block-heading">Phase 4：Cronによる完全自動化</h2>



<p>不条理な遅延を許さない、Xserver内部スケジューラー（Cron）への登録を行います。</p>



<pre class="wp-block-code"><code>0,15,30,45 8-21 * * * cd /home/〇〇/.tdr_system/fetcher &amp;&amp; /home/〇〇/.nodebrew/current/bin/node index.js >> /home/〇〇/.tdr_system/fetcher/debug.log 2>&amp;1</code></pre>



<figure class="wp-block-image size-full"><img decoding="async" width="1339" height="125" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/02/image-5.png" alt="" class="wp-image-13056"/></figure>



<p>※〇〇にはサーバーIDを入れてください。</p>



<h2 class="wp-block-heading">WordPressへのリアルタイム連携</h2>



<p>蓄積されたデータをブログで表示するため、GAS側にデータ取得用のAPI（doGet）を追加し、WordPress側でショートコードを作成します。</p>



<h3 class="wp-block-heading">1. GASコードの追加 (doGet)</h3>



<p>先ほどのGASプロジェクトに以下の関数を追加し、再度デプロイ（バージョンアップ）してください。</p>



<pre class="wp-block-code"><code>function doGet(e) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName("蓄積ログ");
  
  // 最新の77件（アトラクション数分）だけを取得して返す例
  const lastRow = sheet.getLastRow();
  // ヘッダー行のみの場合は空を返す
  if (lastRow &lt;= 1) return ContentService.createTextOutput("&#91;]");
  
  // 過去の膨大なログから直近のデータのみ抽出
  // ※ここでは簡易的に末尾100行を取得するロジックとします
  const startRow = Math.max(2, lastRow - 100); 
  const data = sheet.getRange(startRow, 1, lastRow - startRow + 1, 7).getValues();
  
  // 最新の run_id を持つデータのみにフィルタリング
  const lastRunId = data&#91;data.length - 1]&#91;6]; // 6番目=run_id
  const latestData = data.filter(row => row&#91;6] === lastRunId);
  
  const headers = &#91;"park", "name", "waitTime", "status", "area", "updateTime", "run_id"];
  const result = latestData.map(row => {
    let obj = {};
    headers.forEach((h, i) => obj&#91;h] = row&#91;i]);
    return obj;
  });

  return ContentService.createTextOutput(JSON.stringify(result))
    .setMimeType(ContentService.MimeType.JSON);
}</code></pre>



<h3 class="wp-block-heading">2. WordPress (functions.php)</h3>



<p>以下のコードを追加することで、ショートコード <code>[tdr_wait_list]</code> が使用可能になります。</p>



<pre class="wp-block-code"><code>add_shortcode('tdr_wait_list', function() {
    // GASのウェブアプリURL
    $url = 'https://script.google.com/macros/s/xxxxxxxxxxxxxxxxx/exec';
    
    // Transient APIで60秒間キャッシュ
    $cache_key = 'tdr_data_log';
    $data = get_transient($cache_key);

    if (false === $data) {
        $response = wp_remote_get($url);
        if (is_wp_error($response)) return 'データ取得中...';
        $data = json_decode(wp_remote_retrieve_body($response), true);
        set_transient($cache_key, $data, 60);
    }

    if (empty($data)) return '現在データはありません';

    $html = '&lt;div class="tdr-wait-list">';
    foreach ($data as $row) {
        $wait = ($row&#91;'status'] === 'OPERATING') ? $row&#91;'waitTime'] . '分' : '一時休止';
        if ($row&#91;'status'] === 'CLOSED') $wait = '終了';
        
        $html .= '&lt;div class="attraction-item">';
        $html .= '&lt;span class="name">' . esc_html($row&#91;'name']) . '&lt;/span>';
        $html .= '&lt;span class="wait">' . esc_html($wait) . '&lt;/span>';
        $html .= '&lt;/div>';
    }
    $html .= '&lt;/div>';
    return $html;
});</code></pre>



<h2 class="wp-block-heading">まとめ</h2>



<p>本構築により、GitHub Actionsという不透明なリソースを排除し、自らの管理下で「責任の所在」を明確にしたデータ収集基盤が完成し、現在の待ち時間を15分間隔で取得してWordPressで確認できるところまで実装できました。</p>



<p>次は蓄積したデータを基にグラフとして可視化したり、何曜日の何時くらいが空いているのか、何月に人が多いのかなどの情報を他の予測するサイトより、数字に基づいた立証データを出せると思いますので楽しみにお待ちいただければと存じます！</p>



<p>最後までご覧いただきありがとうございました！</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>捨てるな！OptiPlex990をSSDとWin11で「現役事務機」にする手順</title>
		<link>https://numaresearch.com/ura-blog/optiplex-990-ssd-win11-upgrade/</link>
		
		<dc:creator><![CDATA[ぬま畑]]></dc:creator>
		<pubDate>Fri, 02 Jan 2026 09:00:05 +0000</pubDate>
				<category><![CDATA[PC・技術ハック]]></category>
		<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://numaresearch.com/ura-blog/?p=12834</guid>

					<description><![CDATA[もし一つでも当てはまるなら、この記事が「答え」です。 結論から言います。OptiPlex990を捨てないでください！ 5年前のPCでも、正しい手順を踏み、たった1つのパーツを交換すれば、Windows 11の最新バージョ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>Windows 10のサポート終了が迫っているが、会社の古いPCを買い替える予算がない</strong></li>



<li><strong>OptiPlex990が倉庫に眠っているが、Core i5-2500（第2世代）は流石に使い物にならないと思っている</strong></li>



<li><strong>ネット上の『裏技インストール』は難しそうで、失敗してPCを壊すのが怖い</strong></li>
</ul>



<p> もし一つでも当てはまるなら、この記事が「<span class="sbd-text-red">答え</span>」です。 </p>



<p>結論から言います。<strong><span class="sbd-text-red"><span class="sbd-text-bg-yellow">OptiPlex990を捨てないでください！</span></span></strong></p>



<p>5年前のPCでも、正しい手順を踏み、<strong>たった1つのパーツ</strong>を交換すれば、Windows 11の最新バージョン（25H2）が実用レベルで動作します。</p>



<p>必要な追加投資は、<strong><span class="sbd-text-bg-yellow">新品のSSD代（約5,000円〜）のみ</span></strong>です。 これだけのコストで、廃棄寸前のPCが「現役の事務マシン」に生まれ変わります。実際に私が検証した全手順と結果を公開します。</p>



<h2 class="wp-block-heading">【結論】第2世代Core i5でもWindows 11は「サクサク」動く</h2>



<p>まず、論より証拠をご覧ください。これが現実です。</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1644" height="709" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/スクリーンショット-2026-01-02-153826.jpg" alt="Core i5-2500の上で、涼しい顔をして動くWindows 11 Version 24H2" class="wp-image-12835"/></figure>



<p>「無理やりインストールしたら重くなるのでは？」という<span class="sbd-text-red">常識は間違い</span>です。ストレージをHDDからSSDにさえ換えていれば、<span class="sbd-text-bg-yellow">Excelの起動、YouTubeのフルHD再生、複数タブを開いてのブラウジングは驚くほど軽快</span>です。</p>



<p>はっきり言って、ドン・キホーテなどで売られている「現行の格安CeleronノートPC」よりも、この15年前のCore i5の方が遥かに快適に動作します。事務用PCとしての寿命は、これで完全に延びました。</p>



<h2 class="wp-block-heading">なぜ今、あえて「Dell OptiPlex 990」なのか？</h2>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1084" height="845" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-8-1.jpg" alt="" class="wp-image-12845"/></figure>



<p>今回、実験台（兼、私のサブ機）としてOptiPlex 990 Core i5 モデルを選んだのには、明確な理由があります。</p>



<p>圧倒的な安さと流通量、そして中古市場では数千円で投げ売りされているお店も多数あり、多くの中小企業の倉庫にも眠っています。（ただ、2026年1月現在だと購入するのは難しいかもしれません笑）</p>



<p>神がかったメンテナンス性 Dellのこの世代のビジネスPCは、工具不要でケースを開けられ、パーツ交換が容易です。「<strong>壊れても痛くない実験機</strong>」としてこれ以上の素材はありません！</p>



<p>…と言っていますが、家においてあるPCをなんとか有効活用したいなーって思っただけというのは内緒。</p>



<p>第2世代のCore i5搭載のOptiPlex 990は、PCの歴史に残る名機と言っても過言じゃありません。（あ、いや過言かも…。）ITテクニカルアドバイザーの意地として、<span class="sbd-text-bold"><span class="sbd-text-bg-yellow">Windows 11ごときで引退させるには惜しいポテンシャルを持っています</span></span>ので復活させます！</p>



<h2 class="wp-block-heading">準備編：インストールUSBの作成手順（Rufus設定）</h2>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="818" height="548" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-8.png" alt="" class="wp-image-12847"/></figure>



<p>ここからが具体的な手順です。マイクロソフト公式のメディア作成ツールは使いません（要件チェックで弾かれるため）。代わりにフリーソフトの「<strong><span class="sbd-text-red"><span class="sbd-text-bg-yellow">Rufus</span></span></strong>」を使います。</p>



<h3 class="wp-block-heading">用意するもの</h3>



<p>いくつか以下の通りです。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>8GB以上のUSBメモリ</strong>（中身は消えるので注意）</li>



<li><strong><a href="https://www.microsoft.com/ja-jp/software-download/windows11" target="_blank" rel="noreferrer noopener">Windows 11のISOファイル</a></strong>（Microsoft公式サイト等のアーカイブから 25H2 を使用・無料）</li>



<li><strong><a href="https://rufus.ie/ja/" target="_blank" rel="noreferrer noopener">Rufus</a></strong>（ブートUSB作成ツール・無料）</li>



<li><strong>2.5インチ SATA SSD 250GB以上</strong>（※<strong>必須です</strong>。Amazon等で5,000円〜7,000円程度で購入可能）</li>
</ul>



<h3 class="wp-block-heading">【最重要】Rufusの設定</h3>



<p>ISOファイルをRufusに読み込ませ、「スタート」を押した直後に出る<strong>この画面が運命の分かれ道</strong>です。</p>



<p>用意していただいたUSBメモリをPCに接続しRufus-〇〇.exeをダブルクリックで起動します。（〇〇はバージョンです、最新は4.11.2285）</p>



<p>すると以下のようなソフトが立ち上がります。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="429" height="590" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-1.png" alt="" class="wp-image-12837"/></figure>



<p>USBメモリが挿さっていれば、基本的にはブートの種類の右側の「選択」をクリックして</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="934" height="516" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-3.png" alt="" class="wp-image-12839"/></figure>



<p>ダウンロードしたwin11のisoファイルを選択するだけでOKです。スタートを押します。</p>



<p>すると次のようなポップアップが表示されます。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="939" height="490" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-4.png" alt="" class="wp-image-12840"/></figure>



<p>重要なのは赤枠の部分。</p>



<p>必ず、一番上の項目<span class="sbd-text-bg-yellow"><span class="sbd-text-red">「4GB以上のRAM、セキュアブート及びTPM 2.0の要件を削除」</span></span>に<strong>チェック</strong>を入れてください。</p>



<p>これにチェックを入れるだけで、インストーラーが行う「古いCPUお断り」「TPMチップがないとお断り」という厳しいチェックを<strong><span class="sbd-text-red"><span class="sbd-text-bg-yellow">全て無効化（スキップ）</span></span></strong>できます。 これ以外に難しい設定は一切不要です。</p>



<p>作成に結構時間かかりますが、5～10分ほどお待ちください。</p>



<h2 class="wp-block-heading">実践編：エラーゼロでデスクトップまで到達</h2>



<p>覚悟して挑みましたが、正直に言うと<strong><span class="sbd-text-bg-yellow">「書くことがない」ほとんどないくらい、</span><span class="sbd-text-bg-yellow">驚くほど</span><span class="sbd-text-bg-yellow">普通にインストールできました。</span></strong></p>



<p>作成したUSBメモリをOptiPlex 990に挿し、デスクトップにあるPCアイコン→USBメモリを選択、</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="319" height="116" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-5.png" alt="" class="wp-image-12841"/></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="218" height="302" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-6.png" alt="" class="wp-image-12842"/></figure>



<p>setup.exeをダブルクリックして、インストーラーを起動してあとは通常のWindowsインストールと同じ画面が進んでいきます。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li>ブルースクリーン？　→　<strong>出ません。</strong></li>



<li>「このPCは要件を満たしていません」という警告？　→　<strong>出ません。</strong></li>



<li>途中の再起動でのフリーズ？　→　<strong>ありません。</strong></li>
</ul>



<p>写真を撮るタイミングを逃すほどスムーズに進行しまして、気づけば「こんにちは」の画面を経てデスクトップが表示されていました。この「あっけなさ」こそが、Rufusを使ったクリーンインストールの最大のメリットですね。</p>



<h2 class="wp-block-heading">検証編：ドライバとセキュリティは大丈夫か？</h2>



<p>「入ったとしても、音が出ないとか画面がおかしいとかあるんでしょ？」 そう疑っている方、検証結果をお見せします！</p>



<h3 class="wp-block-heading">1. デバイスドライバの認識状況</h3>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="564" height="659" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-7.png" alt="" class="wp-image-12843"/></figure>



<p>驚くべきことに、Windows 11標準のWindows Updateを回しただけで、Dell特有のチップセットやオーディオドライバが<strong>ほぼ全て自動で当たりましたしなんの支障もエラーもなかったです。</strong> 「不明なデバイス」を探してネットを彷徨う必要はありません。現代のOSの対応力は凄まじいですね。</p>



<h3 class="wp-block-heading">2. アイドル時の負荷状況</h3>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1682" height="872" src="https://numaresearch.com/ura-blog/wp-content/uploads/2026/01/image-8.jpg" alt="" class="wp-image-12844"/></figure>



<p>起動してからYouTubeを見てみました。CPU使用率は10～40％（安定はしませんけど、まぁこれはYouTubeの特性である意味で一定です）、メモリ消費も一定であり、落ち着いています。</p>



<p>バックグラウンドで不要なプロセスが暴走することもなく、非常に安定しています。これが「クリーンインストール」の強みでもありますね。</p>



<h2 class="wp-block-heading">余談：SSDの交換について</h2>



<p>OptiPlex 990は元々はSSDではなくHDDが搭載されていました。</p>



<p>2～3年前にSSDへ換装しており、今回換装自体は端折っております。</p>



<p>なお、SSDに交換するにはその当時、EaseUSという会社の無料のクローンソフト（バックアップ兼起動可能）がありまして、クローンを作りSSDへの換装を行えておりました。</p>



<p>ですが現在は改悪され、無料でクローンを作れなくなりました・・・が！最近ではAcronisというソフトを使用して、完全無料でクローンを作成することが可能です。</p>



<p>Google検索やYouTube等で換装方法はいくらでも出てきますのでご参照ください。</p>



<p>一応必要なものを置いておきます。</p>



<p>＼安定のWD製SSDです／</p>


<div id="rinkerid12848" class="yyi-rinker-contents  yyi-rinker-postid-12848 yyi-rinker-img-m yyi-rinker-catid-174 yyi-rinker-catid-69 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09TMZ1MF8?tag=snake4610-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A" data-vars-click-id="amazon_img 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A"><img decoding="async" src="https://m.media-amazon.com/images/I/31JM3BMk-ML._SL160_.jpg"  width="160" height="160" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09TMZ1MF8?tag=snake4610-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A" data-vars-amp-click-id="amazon_title 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A" >Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="brand">ウエスタンデジタル(Western Digital)</div>
							<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=SSD+250GB&amp;tag=snake4610-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A"  data-vars-amp-click-id="amazon 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/1326c050.cb5c8da6.1326c051.6bd9c169/Rinker_o_20260102224000?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FSSD%2B250GB%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FSSD%2B250GB%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A"  data-vars-amp-click-id="rakuten 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A">楽天市場</a>					</li>
													<li class="yahoolink">
						<a href="https://ck.jp.ap.valuecommerce.com/servlet/referral?sid=3520560&amp;pid=890573138&amp;vc_url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DSSD%2B250GB" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="yahoo 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A"  data-vars-amp-click-id="yahoo 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://ad.jp.ap.valuecommerce.com/servlet/gifbanner?sid=3520560&#038;pid=890573138" height="1" width="1" border="0">					</li>
				                                    <li class="mercarilink">
                        <a href="https://jp.mercari.com/search?keyword=SSD%20250GB&amp;utm_source=Rinker&amp;afid=1114332298" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="mercari 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A"  data-vars-amp-click-id="mercari 12848 Western Digital (ウエスタンデジタル) 240GB WD Green 内蔵SSD ソリッドステートドライブ &#8211; SATA III 6Gb/秒 2.5インチ/7mm 最大545MB/秒 &#8211; WDS240G3G0A">メルカリ</a>                    </li>
                											</ul>
					</div>
	</div>
</div>



<p>＼こちらも安定な玄人志向のお立ち台／</p>


<div id="rinkerid12849" class="yyi-rinker-contents  yyi-rinker-postid-12849 yyi-rinker-img-m yyi-rinker-catid-174 yyi-rinker-catid-69 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09NN1MMDY?tag=snake4610-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="amazon_img 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3" data-vars-click-id="amazon_img 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3"><img decoding="async" src="https://m.media-amazon.com/images/I/419iBXqA8NL._SL160_.jpg"  width="160" height="160" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09NN1MMDY?tag=snake4610-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="amazon_title 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3" data-vars-amp-click-id="amazon_title 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3" >玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="brand">玄人志向</div>
							<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=SSD+USB+%E3%83%89%E3%83%83%E3%82%AF&amp;tag=snake4610-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3"  data-vars-amp-click-id="amazon 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/1326c050.cb5c8da6.1326c051.6bd9c169/Rinker_o_20260102224140?pc=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FSSD%2BUSB%2B%25E3%2583%2589%25E3%2583%2583%25E3%2582%25AF%2F%3Ff%3D1%26grp%3Dproduct&amp;m=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FSSD%2BUSB%2B%25E3%2583%2589%25E3%2583%2583%25E3%2582%25AF%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3"  data-vars-amp-click-id="rakuten 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3">楽天市場</a>					</li>
													<li class="yahoolink">
						<a href="https://ck.jp.ap.valuecommerce.com/servlet/referral?sid=3520560&amp;pid=890573138&amp;vc_url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DSSD%2BUSB%2B%25E3%2583%2589%25E3%2583%2583%25E3%2582%25AF" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="yahoo 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3"  data-vars-amp-click-id="yahoo 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://ad.jp.ap.valuecommerce.com/servlet/gifbanner?sid=3520560&#038;pid=890573138" height="1" width="1" border="0">					</li>
				                                    <li class="mercarilink">
                        <a href="https://jp.mercari.com/search?keyword=SSD%20USB%20%E3%83%89%E3%83%83%E3%82%AF&amp;utm_source=Rinker&amp;afid=1114332298" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="mercari 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3"  data-vars-amp-click-id="mercari 12849 玄人志向 外付け 3.5 型 / 2.5 型 SATA 接続 HDD/SSD スタンド お立ち台 USB3.2 Gen1 対応 最大容量 32TB ドライブ換装 【国内正規品】 KURO-DACHI/CLONE/CRU3">メルカリ</a>                    </li>
                											</ul>
					</div>
	</div>
</div>



<h2 class="wp-block-heading">まとめ：5,000円のSSD投資で、PC寿命はあと3年延びる</h2>



<p>今回の検証結果をまとめます。</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>OptiPlex 990（Core i5-2500）は、Windows 11でも現役性能を発揮する。</strong></li>



<li><strong>Rufusを使えば、TPM 2.0やCPU制限は完全に無視できる。</strong></li>



<li><strong>ただし、約5,000円の「SSD換装」は絶対に必要（HDDは不可）。</strong></li>
</ul>



<p>逆に言えば、<strong>「飲み会1回分のコスト」</strong>で、廃棄寸前のPCが「最新OS搭載のサブ機」に生まれ変わるということです。コストパフォーマンスという意味では、最強の部類に入ります。</p>



<p>Windows 10のサポート終了に怯えて、使えるPCを捨てるのはやめましょう。技術と知恵があれば、まだまだ彼らは働けます！</p>



<h3 class="wp-block-heading">【法人・個人事業主の方へ】そのPC、廃棄する前にご相談ください</h3>



<p>「記事の手順通りにやればできることは分かった。しかし……」</p>



<ul class="wp-block-list is-style-sbd-border-orange">
<li><strong>「社内にある10台以上のPCを、一台ずつ設定して回るのは面倒すぎる」</strong></li>



<li><strong>「万が一、失敗して重要なデータが消えたら怖い」</strong></li>



<li><strong>「SSDへの換装作業なんて、ドライバーを握ったこともないから不安だ」</strong></li>
</ul>



<p>そんな経営者様・担当者様へ。 「Creative Swamp」では、<strong>『中小企業向けPC延命リフレッシュ代行』</strong>も行っています。</p>



<p>面倒なインストール作業、SSD換装、メモリ増設、内部清掃まで、全てワンストップで代行いたします。新品の法人用PCを買い替えるコストの<strong>1/5以下</strong>で、快適でセキュアなWindows 11環境を構築しませんか？</p>



<p>まずは<strong>「PCの型番」と「台数」</strong>をご連絡ください。既存の環境を調査し、最適な延命プランをお見積りいたします。</p>



<p><strong>[<a href="https://numa-log.com/inquiry/"> >> お問い合わせ・見積もり依頼はこちら（フォームへ移動）</a> ]</strong></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
