巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片

本代码已经升级:

巧用ChatGPT改造代码 让PIX主题片刻支持外部链接转化为卡片(二) 巧用ChatGPT改造代码 让PIX主题片刻支持外部链接转化为卡片(二) 本文更新于2024/10/18,如无重大BUG,本文不再更新。 这是让我最伤脑子的改造,网络上每个站点的安全配置不同,网速不同,让我不能完全照顾到所有网站。并且对于大型网站由于安全性太高,如某宝、某猫... 时间:2024/10/14 分类:技术相关

改造代码最开始的目的是看到其他hexo的网站上有“分享好物”的功能,可以推广但不限于淘宝、京东商品,我的是wordpress网站,搜索没有相关的插件,但也想搞一个,可惜没有成功。后来看到PIX自带的卡片功能,不过默认仅支持本地链接,包括文章、页面、片刻等,如果想分享好物或者好的链接地址,是无法转化为卡片的,所以就有了改造代码的想法。但是我对代码一窍不通,所以想到了用ChatGTP帮我改造。

一、改造代码的运行逻辑:

在现有的代码上新增判断,如果是本站链接,处理源代码不变;如果是外部链接,先分析外部链接源码,查找是否存在logo标签,有的话取logo标签值作为卡片图像,没有的话查找是否存在icon标签,有的话取icon标签值作为卡片图像,logo优先级大于icon,图像格式包括但不限于jpg/jpeg/gif/png/webp/svg等,查找是否存在title或者name标签,如果有取title或者name标签值作为卡片标题,查找是否存在des或者desc或者description标签,如果有取des或者desc或者description标签值作为卡片描述。

二、目前已知的BUG:

改造的代码并不完美,有一些外部网站,并不能获取信息。一种是像天猫、阿里巴巴1688这些使用动态的完全无法获取,及时获取了也会500、502错误造成自己的网站打不开或者缓慢,只能从数据库中删除相关网址;一种是获取不完全,就是图像、标题和描述三者只取一二,但是网址都可以获取,目前不清楚是何原因造成的,原以为是目标网址使用了CND或者防盗链,但都做了处理还是不行。

BUG注意事项在卡片页面已经做了提示。

巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年

三、改造过程:

涉及到以下文件:

1、在pix/inc目录下新增simple_html_dom.php、Debug.php、HtmlDocument.php、HtmlNode.php和constants.php,其中主要是simple_html_dom.php。

2、改造pix/inc/pix-type.php,所有的代码都在这里了。

查找以下代码,从这里开始,如果没有改动过文件,大概在65行:

// 获取卡片信息
function get_card_by_url($data) {

查找以下代码,从这里的上面结束,如果没有改动过文件,大概在171行,也就是改造结束在169行:

//音乐编辑---------------------------------------------------------------------------------------------------------------------------------
function audio_type_box(){

我们要改造的就是中间的代码,替换成以下代码:

[reply]

// 卡片------------------------------------------------------
function head_append_meta() {
    $metas = [
        'og:title'     => get_the_title(),
        'og:site_name' => get_bloginfo( 'name' ),
        'og:type'      => 'website',
    ];
    if ( is_single() || is_page() ) {
        $type = get_post_type();
        $metas['og:url']         = get_permalink();
        $metas['og:description'] = get_the_excerpt();

        $meta_image_url = cst_get_thum( get_the_ID(), 'large');
        if ( $meta_image_url ) {
            $metas['og:image'] = $meta_image_url;
        }
        
        $metas['og:type'] = get_post_type();

        if($type == 'moment'){
            $metas['og:title'] = get_the_title() ? get_the_title() : get_the_excerpt();
            $moment_img = THEME_URL.'/img/banner.jpg';
            $lists = get_post_meta(get_the_ID(),'moment_ga',true);
            if(is_array($lists) && !empty($lists)){
                $moment_img = $lists[0]['thum'];
            }
            $metas['og:image'] = $moment_img;
        }
    }
    foreach ( $metas as $key => $value ) {
        echo '<meta property="' . $key . '" content="' . $value . '" />' . "\n";
    }
}

add_action( 'wp_head', 'head_append_meta', 1 );   

//获取卡片信息
// Add this function to retrieve the logo or favicon for external links
require_once('simple_html_dom.php');

function get_external_link_logo($url) {
    $parsed_url = parse_url($url);
    $favicon_url = $parsed_url['scheme'] . '://' . $parsed_url['host'] . '/favicon.ico';

    // Check if the favicon exists
    $ch = curl_init($favicon_url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $response_code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    if ($response_code == 200) {
        return $favicon_url;
    } else {
        // If the favicon doesn't exist, try to retrieve the website's logo
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $html = curl_exec($ch);
        curl_close($ch);

        $doc = str_get_html($html);

        $images = $doc->find('img');
        foreach ($images as $image) {
            $src = $image->src;
            $alt = $image->alt;

            if (stripos($src, 'logo') !== false || stripos($alt, 'logo') !== false ||
                stripos($src, 'icon') !== false || stripos($alt, 'icon') !== false) {
                // Check if the logo URL is relative or absolute
                if (strpos($src, 'http') === false) {
                  $src = $parsed_url['scheme'] . '://' . $parsed_url['host'] . '/' . ltrim($src, '/');
                } elseif (strpos($src, 'https') !== 0) {
                  $src = str_replace('http://', 'https://', $src);
                }
                return $src;
            }
        }
    }

    return '';
}

function get_external_link_metadata($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $html = curl_exec($ch);
    curl_close($ch);

    $doc = str_get_html($html);

    $meta = array();

    // Get the image
    $source_code = $doc->outertext;
    $logo_pattern = '/<\s*logo[^>]*>(.*?)<\s*\/\s*logo\s*>/si';
    $icon_pattern = '/<\s*icon[^>]*>(.*?)<\s*\/\s*icon\s*>/si';

    // Find logo tag and extract image source
    preg_match($logo_pattern, $source_code, $logo_matches);
    if (!empty($logo_matches)) {
        $image_source = extract_image_source($logo_matches[1]);
        if ($image_source) {
            $meta['image'] = $image_source;
        }
    }

    // Find icon tag and extract image source if logo not found
    if (empty($meta['image'])) {
        preg_match($icon_pattern, $source_code, $icon_matches);
        if (!empty($icon_matches)) {
            $image_source = extract_image_source($icon_matches[1]);
            if ($image_source) {
                $meta['image'] = $image_source;
            }
        }
    }

    // Get the title
    $title_pattern = '/<\s*(?:title|name)[^>]*>(.*?)<\s*\/\s*(?:title|name)\s*>/si';
    preg_match($title_pattern, $source_code, $title_matches);
    if (!empty($title_matches)) {
        $meta['title'] = $title_matches[1];
    } else {
        $meta['title'] = '';
    }

    // Get the description
    $des_pattern = '/<\s*(?:des|desc|description)[^>]*>(.*?)<\s*\/\s*(?:des|desc|description)\s*>/si';
    preg_match($des_pattern, $source_code, $des_matches);
    if (!empty($des_matches)) {
        $meta['des'] = $des_matches[1];
    } else {
        $meta['des'] = '';
    }

    return $meta;
}

function extract_image_source($tag_content) {
    $image_pattern = '/(?:src|href)\s*=\s*["\']([^"\']+\.(?:jpg|jpeg|png|gif|webp|svg))["\']/i';
    preg_match($image_pattern, $tag_content, $image_matches);
    if (!empty($image_matches)) {
        return $image_matches[1];
    }
    return null;
}

function get_card_by_url($data) {
    $parsed_url = parse_url($data);
    $pid = null;

    if (filter_var($data, FILTER_VALIDATE_URL)) {
        if ($parsed_url['host'] == $_SERVER['HTTP_HOST']) {
            $pid = url_to_postid($data);
        } else {
            $pid = $data;
        }
    } else {
        $pid = intval($data);
    }

    if ($pid) {
        $type = '';
        $meta = array();

        if (filter_var($pid, FILTER_VALIDATE_URL)) {
            $meta['url'] = $pid;

            $external_meta = get_external_link_metadata($pid);
            $meta['title'] = $external_meta['title'];
            $meta['des'] = $external_meta['des'];
            $meta['image'] = get_external_link_logo($pid);
        } else {
            $type = get_post_type($pid);
            $meta['title'] = get_the_title($pid);
            $meta['url'] = get_permalink($pid);
            $meta['des'] = get_the_excerpt($pid);
            $meta_image_url = get_the_post_thumbnail_url($pid, 'medium');

            if ($meta_image_url) {
                $meta['image'] = $meta_image_url;
            } else {
                $meta['image'] = get_external_link_logo($meta['url']);
            }

            if ($type == 'moment') {
                $meta['title'] = '片刻';
                $moment_img = THEME_URL.'/img/banner.jpg';
                $lists = get_post_meta($pid,'moment_ga',true);
                if(is_array($lists) && !empty($lists)){
                    $moment_img = $lists[0]['thum'];
                }
                $meta['image'] = $moment_img;
            }
        }

        $meta['pid'] = $pid;
        return $meta;
    } else {
        return false;
    }
}

function get_image_proxy_url($url) {
    $proxy_url = '';
    $proxy_script_url = 'https://proxyium.com/zh-CN/'; // 代理脚本的URL

    $response = wp_remote_get($proxy_script_url, array(
        'timeout' => 10,
        'headers' => array(
            'Referer' => $url,
        ),
        'body' => array(
            'url' => $url,
        ),
    ));

    if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
        $body = wp_remote_retrieve_body($response);
        $proxy_url = $body;
    }

    return $proxy_url;
}

//卡片编辑
function card_type_box(){
    $output = '';
    $output = '<div class="add_card_box">
                    <div class="edit_card_box">
                        <div class="tips"># 输入本站网址或外部网址,自动生成链接卡片</div>
                        <div class="tips">
                           <span>1、本站网址支持文章、 片刻、页面等,外部网址尽量简化(有一定几率外部网址无法生成或错误)。</span><br>
                           <span>2、外部网站转化图片时,遇到500、502、301、302等错误,就取消操作,不然要么打开首页或片刻页很慢,要么就需要在数据库中把相关错误网址删除。</span><br>
                           <span>淘宝示例:https://item.taobao.com/item.htm?id=******<br>京东示例:https://item.jd.com/******.html<br>拼多多示例:https://mobile.yangkeduo.com/goods1.html?goods_id=******</span></div>
                        <div class="edit_content">
                            <input type="text" placeholder="本站网址或外部网址" name="moment_card_link" id="moment_card_link" required="required">
                            <a class="push_card">生成卡片</a>
                        </div>
                    </div>
                    <div class="show_card"><div class="card_sortble" uk-sortable="handle: .moment_card_item"></div></div>
                </div>';
    echo $output;  
    exit();         
}
add_action('wp_ajax_nopriv_card_type_box', 'card_type_box');
add_action('wp_ajax_card_type_box', 'card_type_box');



function get_moment_card(){
    $card_url = esc_url($_POST['card_url']);
    $arr = get_card_by_url($card_url);
    $html = '';

    if(is_array($arr)){
        $html = '<div class="moment_card_item" pid="'.$arr['pid'].'">
                    <a>
                        <div class="left"><img src="'.$arr['image'].'"></div>
                        <div class="right"><h4>'.$arr['title'].'</h4><div class="content">'.$arr['des'].'</div></div>
                        <span class="de_card"><i class="ri-close-line"></i></span>
                    </a>
                </div>';
        $res = array('html' => $html,'state' => '1');        
    } else {
        $html = '未知错误';
        $res = array('html' => $html,'state' => '0');  
    }

    echo json_encode($res);
    exit();

}
add_action('wp_ajax_nopriv_get_moment_card', 'get_moment_card');
add_action('wp_ajax_get_moment_card', 'get_moment_card');

function get_m_card(){
    global $post;
    $pid = $post->ID;
    $lists = get_post_meta($pid,'moment_card',true);
    $html = '';
    if(is_array($lists) && !empty($lists)){
        foreach($lists as $index => $list){
                $arr = get_card_by_url($list);
                $html .= '<div class="moment_card_item loop_card_item" pid="'.$list.'">
                            <a href="'.$arr['url'].'" target="_blank">
                                <div class="left"><img src="'.$arr['image'].'"></div>
                                <div class="right"><h4>'.$arr['title'].'</h4><div class="content">'.$arr['des'].'</div></div>
                            </a>
                        </div>';             
        }
        return '<div class="card_list">
                    <div class="list_inner">'.$html.'</div>
                </div>';
    }
 
} 

[/reply]

这中间有一句替换成你自己的,其实我也不知道这个到底有用没有,本来是处理目标外部链接CDN和防盗链用的,但好像没啥效果,该不显示的还是不显示:

$proxy_script_url = 'https://proxyium.com/zh-CN/'; // 代理脚本的URL

四、改造效果:

巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年
正常获取
巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年
哔哩哔哩获取不到标题和描述
巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年
正常获取
巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年
淘宝获取不到标题和描述,拼多多获取不到图像和描述。

彩蛋:如果觉得以上卡片宽度太窄,要和下面的点赞分享评论一样宽,只需要调整pix/inc/assets/css/main.css里的代码。

查找一下代码,大概在4326行:

.moment_card_item {
    width: 100%;
    max-width: 500px;
    position: relative;
    margin-bottom: 5px;
}

把max-width的值由原300px改为500px即可。

巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片-似水流年

改造到此结束,用到的文件:

https://www.123pan.com/s/bqeA-kmj1H.html

提取码:V4Xr

Comments | 2 条评论
  • 麦涛

    Microsoft Edge 119 Microsoft Edge 119 Windows 10 Windows 10 1中国–上海–上海 电信/电信CN2 ip address 58.32.*.*

    本来想在博客生成你这篇文章的卡片的,生成以后整个网站每次打开都好卡,只能想撤下了。😂

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国–河南–漯河 联通 ip address 42.238.*.*

      这个看原网站的打开速度,并且有很大的几率生成不了卡片。

消息盒子
# 您需要首次评论以获取消息 #
# 您需要首次评论以获取消息 #

只显示最新10条未读和已读信息