はじめに
突然ですが、みなさんは「誰かが作った人気記事を片っ端から自動収集し、ある程度再構成して自分のサイトで再配信したらどうなるだろう?」
と考えたことはありませんか?
私はまさにその発想のもと、『記事パクリクローラを回して生成AIで整えるサイト』を作成してみました。ところが、公開して数カ月が経過してもトラフィックはゼロ。ログを見返すと、クローラのアクセスもほとんどなく、完全に爆死してしまいました…。
著作権的に問題があるかもしれないという視点については、ひとまず置いておきます。もしその点に引っかかる方は、このままブラウザバックしてください(笑)。正直、怒られそうな内容をつらつらと書いています。
「なぜ誰も来なかったのか?」という疑問について調査した結果や、その対策も含めて本記事でお話ししたいと思います。
作成に至った背景
普段、テレビやラジオ、ニュース記事をほとんど見ない私ですが、「SEOではページ数や更新頻度が重要」
という話を聞いて、あるアイデアが浮かびました。
具体的には、話題の記事を自動収集して生成AIで要約・再構成し、自サイトに大量投稿すれば、バッチ処理で完全自動運用してもアクセスをさばききれるのでは?広告収入も得られるのでは?というものです。これが本プロジェクトのスタート地点です。
とりあえず目標を決める
私は SEO の専門家ではないため、緻密な施策立案や効果検証を行うよりも、まずは実践を通じて学ぶアプローチを選びました。そこで以下の大枠を KPI として設定しました。
項目 | 目標 |
---|---|
月額運用コスト | システム全体で月額 5,000 円以内 |
記事生成数 | 1,000 本 / 日 |
さらに、予期しないアクセス増加に備えて、サービスの無停止でデータ移行できる仕組みも導入しました。
自分自身の人件費や作業時間は考慮せず、あくまで趣味のプロジェクトとして進めています。
これらの目標を基に、自動収集・生成AIを用いたバッチ運用を開始し、結果から改善点を見つけるスタイルで進めています。
上記を達成するために描いたシステム設計
自宅のインターネット環境はIPアドレスが固定されていないため、家庭用サーバを使うことはできません。そのため、クラウドサービスで安価に運用し、スケーリングしやすい構成にする必要がありました。
最終的に以下の構成に落ち着きました。
項目 | インフラ |
---|---|
アプリケーション | Lambda + API Gateway |
DB | RDS(単一インスタンス) |
バッチサーバ | オンプレミス |
本番環境のデータ更新時にのみ踏み台サーバを立ち上げ、RDSにバッチサーバからアクセスする形にしました。
データ収集対象とクローラの設計
本プロジェクトでは、以下の条件を満たす記事を自動収集の対象としました。
-
収集対象サイト: 一般的なニュースメディアやブログ
-
収集対象ではないサイト: SNS や動画サイト
SNSや動画サイトを除外した理由は、認証が必要だったり、HTMLの文字列として意味のある内容を取得することが難しいからです。
検索キーワードの取得フロー
記事を作成するために必要なタイトルを決めるロジックは非常に重要です。特にスキャンダル系の記事は鮮度が命ですし、その人気が急上昇するタイミングを見極めることが重要です。
今回は、Google Trends
の「急上昇中」の検索キーワードを24時間、48時間、7日間の期間で取得し、重複を削除した上でデイリーで取得しています。その後、取得したキーワードはテーブルに保存し、次のバッチプロセスで利用します。
記事の掲載されている URL の取得フロー
当初はGoogle Custom Search API
を使ってデータを取得していましたが、収集対象外のサイトが多く含まれてしまうことと、API利用料金が高額だったため、最終的にはGoogle News
のXML出力を利用することにしました。
この方法で、1つのキーワードにつき20記事分のURLを取得できます。取得したURLは、そのままだとリダイレクト処理が入るため、加工する必要があります。その後、加工したURLをテーブルに保存し、次のバッチプロセスに回します。
取得した URL へのクローリングフロー
取得したURLを分析してみると、特にYahooニュース
からの記事が多いことがわかりました。自宅のIPアドレスは1つしかないため、短時間で大量のアクセスを行うとブロックされる可能性があります。
そのため、クローリング部分は外部サーバを使用し、複数のIPアドレスに分散して実行することにしました。今回は、コストパフォーマンスが良く、使用した時間分だけ料金がかかるAWS Lambda
を使用しました。
Lambdaを使い、各URLにアクセスしてHTML内容を取得し、テーブルに保存します。ただし、jsのレンダリングを待つことが難しいため、selenium
やplaywright
は使用せず、シンプルにHTTPリクエストのレスポンスを取得しました。
取得した html の加工と内容の確認
取得したHTMLだけでは意味がわからないため、生成AIを使って内容を要約してもらいます。私はGeminiのAPIの無料枠を使い、記事を要約してもらいました。
出力された内容は、title
、contents
、meta_keywords
、meta_description
、summary
の5項目に分けて取得し、保存します。
作成された記事の類似度を計算する
記事の類似度を事前に計算しておくことで、運用時の苦労を減らせる可能性があります。DBにはPostgreSQLを使用していたので、pg_trgm
を試しましたが、あまり良い結果が得られなかったため、Amazon Bedrock
のamazon.titan-embed-text-v2:0
モデルを使用することにしました。
使ってみたところ、固有名詞系は正直まだ弱い印象でしたが、違和感のない範囲で使用できました。
これで、類似度の高い記事を事前に5件ピックアップし、テーブルに保存してデータ加工プロセスを完了しました。
類似度の高い記事を 5 件出力してテーブルに事前に保存してデータ加工プロセスは完了です。
最後に sitemap.xml
を更新して終了です。
初期運用結果とログ分析
数カ月の運用の結果いくつかのことがわかってきました。
バッチの挙動
クロール数は初回で1,000件近くの記事を取得できましたが、翌日には600件、最終的には1日あたり400件程度に減少しました。キーワードの重複が影響しています。
そのため、重複を削除する期間を30日から14日に変更しましたが、記事数の改善にはつながりませんでした。
アクセス件数
GoogleやBingにサイトマップのURLを送信しましたが、1日あたり平均20件程度のアクセスしかありませんでした。最初は気にしていませんでしたが、何カ月経っても変わらず、悪質なパクリサイトとして認識されてしまったのだと感じています。
かかったコスト
月額 6,000 円くらいかかっていました。詳しくは見ていませんが EC2 Other と VPC が想定より高く、 RDS は予想よりも少なかったです。
結論
他人のコンテンツを簡単にパクるだけでは、成功しないという教訓を得ました。時間を削って作成したアプリも、結局は供養のために続編を書こうと思っています。