LLMO対策の前手順として、マークダウン記法を施しました.

2025.09.02

Logging

おはようございます.LLMO対策の前手順として、マークダウン記法を施しました.シングルページにマークダウン記法のリンクがそれぞれの記事にあると思います.

そのリンクをクリックするとマークダウン記法が表示されます.LLMO設置後、LLMs.txtを設置すれば良いらしいので、そちらも近日中に対応する予定です.尚、この記事がUPされている頃にはLLMs.txtの設置が終わっている気もします.

追伸:LLMs.txtの設置が終わりました、ルートに設置しています.LLMs.txtはマークダウン記法が記載されているURL(リンク)を一行ずつ表示するような形式で良いらしいです.

これをチャッピーさんにプラグインにして貰いましたのでお裾分けです.下記のプラグインを導入すると全記事URL(パラメーター(マークダウン記法と認識させる))が発行されます.

※マークダウン記法したページはご自身で作る必要があります.

<?php
/*
Plugin Name: LLMS URL Exporter (Fixed)
Description: 公開記事のURLをuploads/llms.txt に日付降順で出力します。管理画面のボタンで非同期(AJAX)実行。新規公開時は先頭に追記。
Version: 1.1
Author: taoka toshiaki
*/

if ( ! defined( 'ABSPATH' ) ) exit;

class LLMS_URL_Exporter {
    private $file;

    public function __construct() {
        $this->file = $_SERVER['DOCUMENT_ROOT'] . '/llms.txt';

        add_action( 'admin_menu', [ $this, 'add_admin_page' ] );
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_script' ] );

        // AJAX (管理画面からの呼び出し = ログインユーザー用)
        add_action( 'wp_ajax_llms_generate_urls', [ $this, 'generate_urls' ] );

        // 投稿が公開になったとき(状態遷移を監視)
        add_action( 'transition_post_status', [ $this, 'on_transition_post_status' ], 10, 3 );

        register_activation_hook( __FILE__, [ $this, 'create_file_on_activate' ] );
    }

    public function create_file_on_activate() {
        $dir = dirname( $this->file );
        if ( ! is_dir( $dir ) ) {
            wp_mkdir_p( $dir );
        }
        if ( ! file_exists( $this->file ) ) {
            @file_put_contents( $this->file, "" );
        }
    }

    public function add_admin_page() {
        add_menu_page(
            'LLMS URL Exporter',
            'LLMS Export',
            'manage_options',
            'llms-url-exporter',
            [ $this, 'admin_page_html' ]
        );
    }

    public function enqueue_admin_script( $hook ) {
        // 管理画面の当該ページだけに読み込む
        if ( $hook !== 'toplevel_page_llms-url-exporter' ) return;

        // jQuery は管理画面に既に存在
        wp_enqueue_script( 'llms-admin', plugins_url( 'llms-admin.js', __FILE__ ), [ 'jquery' ], '1.0', true );

        wp_localize_script( 'llms-admin', 'LLMS_Ajax', [
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'nonce'    => wp_create_nonce( 'llms_generate_urls_nonce' ),
        ] );

        // もし外部ファイルを用意しないなら、admin_page_html 内の inline script がフォールバックになります。
    }

    public function admin_page_html() {
        ?>
        <div class="wrap">
            <h1>LLMS URL Exporter</h1>
            <p>公開中の全投稿URLを <code>/llms.txt</code> に日付降順で書き出します。</p>
            <button id="llms-generate-btn" class="button button-primary">全記事URLを書き出す</button>
            <div id="llms-result" style="margin-top:12px;"></div>
        </div>
        <?php
        // フォールバック用のインラインスクリプト(もし外部 JS を作らない場合に有効)
        $nonce = wp_create_nonce( 'llms_generate_urls_nonce' );
        $ajax_url = admin_url( 'admin-ajax.php' );
        ?>
        <script type="text/javascript">
        jQuery(function($){
            $('#llms-generate-btn').on('click', function(){
                var $res = $('#llms-result');
                $res.text('処理中...');

                var data = {
                    action: 'llms_generate_urls',
                    _ajax_nonce: (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.nonce : '<?php echo esc_js( $nonce ); ?>')
                };
                var url = (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.ajax_url : '<?php echo esc_js( $ajax_url ); ?>');

                $.post(url, data, function(response){
                    if ( response && response.success ) {
                        $res.html( response.data.message );
                    } else if ( response && response.data && response.data.message ) {
                        $res.html('エラー: ' + response.data.message);
                    } else {
                        $res.html('不明なレスポンス: ' + JSON.stringify(response));
                    }
                }).fail(function(jqXHR, textStatus, errorThrown){
                    $res.html('AJAX エラー: ' + textStatus + ' ' + errorThrown + ' (status: ' + jqXHR.status + ')');
                });
            });
        });
        </script>
        <?php
    }

    // AJAX ハンドラ
    public function generate_urls() {
        // nonce と権限チェック
        check_ajax_referer( 'llms_generate_urls_nonce', '_ajax_nonce' );
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => '権限がありません。' ], 403 );
        }

        $args = [
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'orderby'        => 'date',
            'order'          => 'DESC',
            'posts_per_page' => -1,
            'no_found_rows'  => true,
            'fields'         => 'ids',
        ];

        $posts = get_posts( $args );
        $urls = [];
        foreach ( $posts as $pid ) {
            $permalink = get_permalink( $pid );
            if ( $permalink ) $urls[] = $permalink.'?md=1';
        }

        $content = implode("\n", $urls);


        $written = @file_put_contents( $this->file, $content );
        if ( $written === false ) {
            $err = error_get_last();
            $msg = isset( $err['message'] ) ? $err['message'] : '不明な書き込みエラー';
            wp_send_json_error( [ 'message' => 'ファイル書き込みに失敗しました: ' . $msg ] );
        }

        wp_send_json_success( [ 'message' => 'llms.txt に ' . count( $urls ) . ' 件のURLを書き出しました。' ] );
    }

    // 公開判定:状態遷移で publish になったときに先頭へ追加
    public function on_transition_post_status( $new_status, $old_status, $post ) {
        if ( $post->post_type !== 'post' ) return;
        if ( $new_status === 'publish' && $old_status !== 'publish' ) {
            $url = get_permalink( $post->ID ).'?md=1';

            $current = '';
            if ( file_exists( $this->file ) ) {
                $current = file_get_contents( $this->file );
            }

            // 既存の同一URLがあれば削除して先頭へ
            $lines = array_filter( array_map( 'trim', explode("\n", $current ) ) );
            $lines = array_values( array_diff( $lines, [ $url ] ) );
            array_unshift( $lines, $url );

            $new_content = implode("\n", $lines);

            @file_put_contents( $this->file, $new_content );
        }
    }
}

new LLMS_URL_Exporter();

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, いん, インライン, エラー, お裾分け, クリック, これ, サン, シングル, スクリプト, そちら, それぞれ, ダウン, チェック, チャッピー, とき, パラメーター, ハンドラ, ファイル, フォールバック, フラグ, ページ, ボタン, マーク, ユーザー, よう, リンク, ルート, レスポンス, ログイン, 一行, 下記, 不明, 予定, 先頭, 公開, 処理, 出力, 判定, 削除, 同一, 呼び出し, 場合, 外部, 失敗, 存在, 実行, 対応, 対策, 導入, 当該, 形式, 必要, 手順, 投稿, 新規, 既存, 日付, 明日, 書き込み, 有効, 権限, 状態, 用意, 画面, 発行, 監視, 管理, 自身, 表示, 記事, 記法, 記載, 設置, 認識, 近日, 追伸, 追加, 追記, 遷移, 降順, 非同期,

あのサイトをリニューアルしました。👏、やっとのことで。 #renew #site #よさこい祭り

2022.09.25

Logging

おはようございます、昼間は暑い日もありますが夜は涼しくなりましたね😄。

今日は昨日、一日かけてよさこい祭り動画検索サイトをリニューアルしました。ソースコード(プログラム)も1からやり直しています。表示するのに結構時間がかかっていた部分は瞬時に表示されるように調整しました。

https://yosakoi-video.com/

以前は検索結果が全て表示されるような仕様でしたが、ページに分割して表示されるように変更しました。また、検索ワードを入力すると検索結果(チーム名)が表示される様に変更しました。チーム名を押すとページへ遷移するようになっています。以前より直感的に操作出来る形になったかと思います。

尚、このサイトを作るにあってYOUTUBEのAPIを使用しているのですが、リアルタイムに動画を検索している訳では無くデータで押さえています。そのデータに関しては数ヶ月置きに更新するように致します。何故、データで押さえている理由はAPIの問い合わせに上限があり、その上限数を超える検索結果が返って来なくなる為です。この上限は申請を行えばある程度増やしてくれるそうですが、それでも上限数量を超えると表示されなくなるというデメリットがあるので、データで押さえています😌。

トイウコトデ、よさこい祭り動画検索サイトよろしくお願いします。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

, API, com, https, renew, site, yosakoi-video, youtube, コード, サイト, ソース, チーム, データ, プログラム, ページ, よさこい祭り, リアルタイム, リニューアル, ワード, , 今日, 仕様, 以前, 使用, 入力, 全て, 分割, 動画, 変更, , , 操作, , , 昨日, 昼間, 時間, 検索, 瞬時, 結果, 表示, , 調整, 遷移, 部分,

Yahoo japanサイトのコロナ情報リンク集です。好評に付きVer2。

2020.12.21

Logging

Yahoo japanサイトのコロナ情報リンク集です。好評に付きバージョン2を
作成しました。見た目はこんな感じです。県名をクリックするとYahoo!japanのコロナサイトの
画面が開きます(遷移します)。ほんとは、Yahoo!データをウェブスクレイピングしようと思ったのですが、別にそこまでする必要はないかなと思いとどまり、いまに至っています。
データは国もJSONで公開していますのでわざわざ作ることもないのですけど、自分が見やすいように、時間があれば改善していきます。

追記:時間があったので改善しました。

https://zip358.com/tool/COVID-19-japan/

var ken_json = {};
fetch("./assets/js/ken47.json").then(response => response.json()).then((data)=>{
	let ken = [];
	for (const key in data) {
		ken.push("<a href='#' onClick='c19(\"" + "https://hazard.yahoo.co.jp/article/covid19" + data[key].roman +"\")' onmouseover='c19_f(\"" + data[key].roman.toUpperCase() + "\",\"red\")'' onmouseout='c19_f(\"" + data[key].roman.toUpperCase() + "\",\"#fff\")'>" + data[key].name + "</a>");
	}
	document.getElementById("covid19-link-list").innerHTML = ken.join(",");
	for (const key in data) {
		document.getElementById(data[key].roman.toUpperCase()).setAttribute("fill","#fff");
	}
});

function c19(url){
	window.open(url,"_blank");
}
function c19_f(kenid,color){
	document.getElementById(kenid).setAttribute("fill",color);
}	
{
	"1": {
		"name": "北海道",
		"roman": "hokkaido"
	},
	"2": {
		"name": "青森",
		"roman": "aomori"
	},
	"3": {
		"name": "岩手",
		"roman": "iwate"
	},
	"4": {
		"name": "宮城",
		"roman": "miyagi"
	},
	"5": {
		"name": "秋田",
		"roman": "akita"
	},
	"6": {
		"name": "山形",
		"roman": "yamagata"
	},
	"7": {
		"name": "福島",
		"roman": "fukushima"
	},
	"8": {
		"name": "茨城",
		"roman": "ibaraki"
	},
	"9": {
		"name": "栃木",
		"roman": "tochigi"
	},
	"10": {
		"name": "群馬",
		"roman": "gunma"
	},
	"11": {
		"name": "埼玉",
		"roman": "saitama"
	},
	"12": {
		"name": "千葉",
		"roman": "chiba"
	},
	"13": {
		"name": "東京",
		"roman": "tokyo"
	},
	"14": {
		"name": "神奈川",
		"roman": "kanagawa"
	},
	"15": {
		"name": "新潟",
		"roman": "niigata"
	},
	"16": {
		"name": "富山",
		"roman": "toyama"
	},
	"17": {
		"name": "石川",
		"roman": "ishikawa"
	},
	"18": {
		"name": "福井",
		"roman": "fukui"
	},
	"19": {
		"name": "山梨",
		"roman": "yamanashi"
	},
	"20": {
		"name": "長野",
		"roman": "nagano"
	},
	"21": {
		"name": "岐阜",
		"roman": "gifu"
	},
	"22": {
		"name": "静岡",
		"roman": "shizuoka"
	},
	"23": {
		"name": "愛知",
		"roman": "aichi"
	},
	"24": {
		"name": "三重",
		"roman": "mie"
	},
	"25": {
		"name": "滋賀",
		"roman": "shiga"
	},
	"26": {
		"name": "京都",
		"roman": "kyoto"
	},
	"27": {
		"name": "大阪",
		"roman": "osaka"
	},
	"28": {
		"name": "兵庫",
		"roman": "hyogo"
	},
	"29": {
		"name": "奈良",
		"roman": "nara"
	},
	"30": {
		"name": "和歌山",
		"roman": "wakayama"
	},
	"31": {
		"name": "鳥取",
		"roman": "tottori"
	},
	"32": {
		"name": "島根",
		"roman": "shimane"
	},
	"33": {
		"name": "岡山",
		"roman": "okayama"
	},
	"34": {
		"name": "広島",
		"roman": "hiroshima"
	},
	"35": {
		"name": "山口",
		"roman": "yamaguchi"
	},
	"36": {
		"name": "徳島",
		"roman": "tokushima"
	},
	"37": {
		"name": "香川",
		"roman": "kagawa"
	},
	"38": {
		"name": "愛媛",
		"roman": "ehime"
	},
	"39": {
		"name": "高知",
		"roman": "kochi"
	},
	"40": {
		"name": "福岡",
		"roman": "fukuoka"
	},
	"41": {
		"name": "佐賀",
		"roman": "saga"
	},
	"42": {
		"name": "長崎",
		"roman": "nagasaki"
	},
	"43": {
		"name": "熊本",
		"roman": "kumamoto"
	},
	"44": {
		"name": "大分",
		"roman": "oita"
	},
	"45": {
		"name": "宮崎",
		"roman": "miyazaki"
	},
	"46": {
		"name": "鹿児島",
		"roman": "kagoshima"
	},
	"47": {
		"name": "沖縄",
		"roman": "okinawa"
	}
}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

19, 2, 358, 47, assets, com, covid, fetch, gt, https, JAPAN, JS, json, ken, quot, response, then, tool, var, ver, www, Yahoo, zip, ウェブ, クリック, こと, コロナ, サイト, スク, そこ, データ, バージョン, ピング, ほんと, リンク集, レイ, わざわざ, 作成, 公開, , 好評, 必要, 情報, 感じ, 改善, 時間, 画面, 県名, 自分, 見た目, 追記, 遷移,

ヤフオクサイトで使用できるChrome拡張機能

2020.06.09

Logging

ヤフオクサイトで使用できるChrome拡張機能を作ってみました。昨日から失業手当も無くなったので、心置きなくクラウドワークスで提案営業をしています。やっていて思ったのが、結構、単価が安いぞということです。まだ、案件を頂いていませんが、、、正直なところ、中々難しいかなと思います。

契約数、1件のところに30人とか応募が来るわけです・・・その中から1件選ばれるわけですが、1/30の確率です。最初の1件の案件を取るのも厳しいかなと思います。でも数件の案件が取れればあとには続きそうです。仕事が見つからないので当分、クラウドワークスで頑張ります。ちなみにこのヤフオクの拡張機能ですが次ページに自動で遷移しません。どうもYahooさんがクローラーかどうかを判断しているプログラマを入れているみたいですね。回避するにはグーグルドライバーなんかを入れてPythonあたりで操作したら、ダミーとはわからないでしょうけど、お客様に納品するとなるとひと手間かかるなと思います。

以上、現場からでした?。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

0, , 30, App, Chrome, com, https, jGSKN-s, Pyt, watch, www, Yahoo, youtube, あと, グーグル, クラウド, クローラー, こと, サイト, ところ, ドライバー, プログラマ, ヤフオク, ワークス, , 仕事, 使用, 判断, 単価, 営業, 回避, 失業, 契約, 当分, 応募, 手当, 拡張, 提案, , 昨日, 最初, 案件, 機能, 次ページ, 正直, 確率, 自動, 遷移,

WordPressの404外部リダイレクトプラグインを作りました。

2019.11.16

Logging

WordPressの404外部リダイレクトプラグインを作りました。
ソースコードはこんな感じになってます、、、。
使用される方は下記のURLよりダウンロードを行ってください。
解凍してフォルダをワードプレスのpluginを置く場所へアップロードし
page404goプラグインを有効にしていただければ使用できます。
https://zip358.com/plugin/page404go.zip

<?php
/*
Plugin Name: page404GO!!
Plugin URI: https://zip358.com/plugin/page404go.zip
Description: 404ページを任意のURLへ変換し遷移させる
Author: taoka toshiaki
Version: 1.0
Author URI: https://zip358.com/
*/
add_action( 'wp', function() {
    global $wp;
    $domain = get_option('domain404page')?get_option('domain404page'):"https://zip358.com/";
    if(is_404()){
        wp_redirect($domain.$wp->request);
        exit;
    }
 });
add_action('admin_menu','page404go_setting');
function page404go_setting(){
	add_options_page(
		'zip358.com:プラグイン',
		'404リダイレクト設定',
		'administrator',
		'page404go',
		function(){
            if(isset($_POST["domain404page"])){
                if(preg_match("/https?://.*/$/",$_POST["domain404page"])){
                    $url = $_POST["domain404page"];
                }elseif(preg_match("/https?://.*/",$_POST["domain404page"])){
                    $url = $_POST["domain404page"]."/";
                }else{
                    $url = "https://zip358.com/";
                }
                update_option('domain404page', wp_unslash($url));
            }
            ?>
            <form method="post" action="">
                <h2>リダイレクトドメイン指定</h2>
                <input type="text" style="width:350px" name="domain404page" value="<?=get_option('domain404page')?get_option('domain404page'):""?>" placeholder="https://zip358.com/">
                <?php submit_button(); ?>
            </form>
            <?php
        }
	);
}

著者名  @taoka_toshiaki

※この記事は著者が30代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

1195254834632380416, 358, 404, Author, com, description, go, lt, name, page, php, plugin, status, taoka, toshiak, Twitter, URI, url, WordPress, zip, アップロード, コード, ソース, ダウンロード, フォルダ, プラグイン, プレス, リダイレクト, ワード, 下記, 任意, 使用, 場所, 変換, 外部, 感じ, , 有効, 解凍, 遷移,