巧用ChatGPT改造代码 让PIX主题片刻支持外部链接转化为卡片(三)

本篇为以下文章的再升级版本,主要升级以下2个部分:

1、建立自己的获取任意网页的站标API接口,不再借助第三方https://favicon.im等网站进行解析,避免因第三方网站访问不畅拖慢本站速度。本站采用修改以下源码https://github.com/7xs/getFavicon进行搭建。

2、建立自己的获取微信公众号平台任意文章的公众号图标、公众号名称和文章标题API接口。本站采用修改以下源码https://github.com/jiaopianjun/wxCrawler进行搭建。获取微信公众号平台任意文章的公众号图标为独立功能,不使用第1条获取。需要注意的是,千万不要用此条进行微信公众号文章爬取,否则有封号的危险。

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

先看演示效果:

巧用ChatGPT改造代码 让PIX主题片刻支持外部链接转化为卡片(三)-似水流年

改造过程如下:

一、将以下压缩包解压缩至网站根目录下,即与wp-config.php同级目录。

温馨提示: 此处为隐藏内容,需要评论本文后才能查看.
评论后请刷新一次页面,但注意不要清除缓存,否则还需要再次评论!

二、强烈建议提前备份pix/inc/pix-type.php文件,然后进行修改。依然从大概第65行// 获取卡片信息开始,至//音乐编辑前结束。

// 获取卡片信息
class CardFetcher
{
    private static $instance;
    private $redis;

    private function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    // 获取缓存的 logo
    public function getCachedLogo($url)
    {
        $redisKey = 'logo_'. md5($url);
        $logoFromRedis = $this->redis->hGet('logos', $redisKey);
        if ($logoFromRedis) {
            return $logoFromRedis;
        }

        return null;
    }

    // 缓存 logo
    public function cacheLogo($url, $logo)
    {
        $redisKey = 'logo_'. md5($url);
        $this->redis->hSet('logos', $redisKey, $logo);
        $this->redis->expire('logos', 86400);
    }

    // 获取缓存的元数据
    public function getCachedMetadata($url)
    {
        $redisKey = 'metadata_'. md5($url);
        $metadataFromRedis = $this->redis->hGet('metadatas', $redisKey);
        if ($metadataFromRedis) {
            return json_decode($metadataFromRedis, true);
        }

        return null;
    }

    // 缓存元数据
    public function cacheMetadata($url, $metadata)
    {
        $redisKey = 'metadata_'. md5($url);
        $this->redis->hSet('metadatas', $redisKey, json_encode($metadata));
        $this->redis->expire('metadatas', 86400);
    }
}

// 引入 simple_html_dom.php 文件
require_once 'simple_html_dom.php';

function extractMetaFromHtml($html)
{
    $dom = str_get_html($html);
    $title = '';
    $description = '';

    // 获取标题
    if ($dom->find('title', 0)) {
        $title = trim($dom->find('title', 0)->plaintext);
    }
    if (empty($title)) {
        if ($dom->find('h1', 0)) {
            $title = trim($dom->find('h1', 0)->plaintext);
        }
    }
    if (empty($title)) {
        foreach ($dom->find('meta') as $meta) {
            if ($meta->property === 'og:title' && $meta->content) {
                $title = trim($meta->content);
                break;
            }
        }
    }

    // 获取描述
    foreach ($dom->find('meta') as $meta) {
        if ($meta->name === 'description' && $meta->content) {
            $description = trim($meta->content);
            break;
        }
    }
    if (empty($description)) {
        foreach ($dom->find('meta') as $meta) {
            if ($meta->property === 'og:description' && $meta->content) {
                $description = trim($meta->content);
                break;
            }
        }
    }
    if (empty($description)) {
        $bodyContent = $dom->find('body', 0)->plaintext;
        $words = preg_split('/\s+/', strip_tags($bodyContent));
        $description = implode(' ', array_slice($words, 0, 30));
    }

    return ['title' => $title, 'description' => $description, 'image' => null];
}

function get_external_link_metadata_with_cache($url)
{
    // 设置主流常见的 USERAGENT
    $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36';
    $cacheKey = 'external_link_metadata_'. md5($url);
    $cachedMeta = CardFetcher::getInstance()->getCachedMetadata($cacheKey);
    if ($cachedMeta) {
        return $cachedMeta;
    }

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置超时时间为 5 秒
    $html = curl_exec($ch);
    if ($html === false) {
        error_log("Curl error for URL $url: ". curl_error($ch));
        // 如果获取外部链接内容失败,尝试从缓存中获取默认值或者返回空值
        return ['title' => '', 'description' => '', 'image' => null];
    }
    $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($responseCode === 200 &&!empty($html)) {
        $meta = extractMetaFromHtml($html);
        CardFetcher::getInstance()->cacheMetadata($cacheKey, $meta);
        return $meta;
    } else {
        return ['title' => '', 'description' => '', 'image' => null];
    }
}

function get_external_link_logo($url)
{
    $parsedUrl = parse_url($url);
    if (!$parsedUrl ||!isset($parsedUrl['host'])) {
        return null;
    }

    $domain = $parsedUrl['host'];

    // 判断是否为微信公众平台文章网址
    if (strpos($url, 'https://mp.weixin.qq.com/s/') === 0) {
        // 提取文章ID部分用于文件名
        $articleId = substr($url, strlen('https://mp.weixin.qq.com/s/'));
        $cacheFilePath = '/第一步解压缩你的API物理路径/api/getmpwechat/cache/'. $articleId. '.json';

        // 检查缓存文件是否存在
        if (file_exists($cacheFilePath)) {
            $jsonContent = file_get_contents($cacheFilePath);
            $data = json_decode($jsonContent, true);

            // 恢复转义后的网址(如果有转义处理的话,这里假设转义函数为 `urldecode`,实际可能需要根据具体转义方式调整)
            if (isset($data['url'])) {
                $data['url'] = urldecode($data['url']);
            }

            return $data['headImgUrl'];
        } else {
            // 如果缓存文件不存在,先进行解析并创建缓存文件
            $parseUrl = "https://你的网站域名/api/getmpwechat/crawler.php?url=". $url;
            // 这里可以添加代码使用curl或者其他方式去请求这个解析接口,获取并解析返回的内容,然后创建缓存文件
            // 以下是示例代码,假设返回的是JSON格式数据,实际可能需要根据接口返回格式调整
            $ch = curl_init($parseUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            $response = curl_exec($ch);
            curl_close($ch);

            $data = json_decode($response, true);

            // 创建缓存文件
            file_put_contents($cacheFilePath, json_encode($data));

            return $data['headImgUrl'];
        }
    }

    // 非微信公众平台文章网址,使用原来的方式获取站标
    return "https://你的网站域名/api/getfavicon/{$domain}";
}

function get_card_by_url($data)
{
    $parsedUrl = parse_url($data);
    $pid = null;
    if (filter_var($data, FILTER_VALIDATE_URL)) {
        if ($parsedUrl['host'] == $_SERVER['HTTP_HOST']) {
            if ($post = get_page_by_path($parsedUrl['path'])) {
                $pid = $post->ID;
            }
        } else {
            $pid = $data;
        }
    } else {
        $pid = intval($data);
    }

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

            // 判断是否为微信公众平台文章网址
            if (strpos($pid, 'https://mp.weixin.qq.com/s/') === 0) {
                // 提取文章ID部分用于文件名
                $articleId = substr($pid, strlen('https://mp.weixin.qq.com/s/'));
                $cacheFilePath = '/第一步解压缩你的API物理路径/api/getmpwechat/cache/'. $articleId. '.json';

                // 检查缓存文件是否存在
                if (file_exists($cacheFilePath)) {
                    $jsonContent = file_get_contents($cacheFilePath);
                    $data = json_decode($jsonContent, true);

                    // 恢复转义后的网址(假设转义函数为urldecode,实际可能需根据具体转义方式调整)
                    if (isset($data['url'])) {
                        $data['url'] = urldecode($data['url']);
                    }

                    $meta['title'] = '微信公众平台 - '. $data['author'];
                    $meta['description'] = isset($data['title'])? $data['title'] : (isset($data['msg_title'])? $data['msg_title'] : '');
                    $meta['image'] = get_external_link_logo($pid);
                } else {
                    // 如果缓存文件不存在,先进行解析并创建缓存文件
                    $parseUrl = "https://你的网站域名/api/getmpwechat/crawler.php?url=". $pid;
                    $ch = curl_init($parseUrl);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_HEADER, false);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                    $response = curl_exec($ch);
                    curl_close($ch);

                    $data = json_decode($response, true);

                    // 创建缓存文件
                    file_put_contents($cacheFilePath, json_encode($data));

                    $meta['title'] = '微信公众平台 - '. $data['author'];
                    $meta['description'] = isset($data['title'])? $data['title'] : (isset($data['msg_title'])? $data['msg_title'] : '');
                    $meta['image'] = get_external_link_logo($pid);
                }
            } else {
                $externalMeta = get_external_link_metadata_with_cache($pid);
                $meta['title'] = $externalMeta['title'];
                $meta['description'] = $externalMeta['description'];
                $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['description'] = get_the_excerpt($pid);
            $metaImageUrl = get_the_post_thumbnail_url($pid, 'medium');
            if ($metaImageUrl) {
                $meta['image'] = $metaImageUrl;
            } else {
                $meta['image'] = get_external_link_logo($meta['url']);
            }
            if ($type == 'moment') {
                $meta['title'] = '片刻';
                $momentImg = THEME_URL. '/img/banner.jpg';
                $lists = get_post_meta($pid, 'moment_ga', true);
                if (is_array($lists) &&!empty($lists)) {
                    $momentImg = $lists[0]['thum'];
                }
                $meta['image'] = $momentImg;
            }
        }
        $meta['pid'] = $pid;
        return $meta;
    } else {
        return false;
    }
}

// 卡片编辑
function card_type_box()
{
    $output = '<div class="add_card_box">
                    <div class="edit_card_box">
                        <div class="tips"># 输入本站网址或外部网址,自动生成链接卡片</div>
                        <div class="tips">
                           <span>本站网址支持文章、片刻、页面内链及外链网址</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=******<br>微信公众平台文章示例:https://mp.weixin.qq.com/s/******</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()
{
    try {
        $cardUrl = esc_url($_POST['card_url']);
        $arr = get_card_by_url($cardUrl);
        $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['description']. '</div></div>
                            <span class="de_card"><i class="ri-close-line"></i></span>
                        </a>
                    </div>';
            $res = ['html' => $html, 'state' => '1'];
        } else {
            $html = '未知错误';
            $res = ['html' => $html, 'state' => '0'];
        }
        echo json_encode($res);
        exit();
    } catch (Exception $e) {
        $html = '未知错误';
        $res = ['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()
{
    try {
        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) {
                $cardInfo = get_card_by_url($list);
                if ($cardInfo) {
                    $html.= '<div class="moment_card_item loop_card_item" pid="'. $cardInfo['pid']. '">
                                <a href="'. $cardInfo['url']. '" target="_blank">
                                    <div class="left"><img src="'. $cardInfo['image']. '"></div>
                                    <div class="right"><h4>'. $cardInfo['title']. '</h4><div class="content">'. $cardInfo['description']. '</div></div>
                                </a>
                            </div>';
                }
            }
            return '<div class="card_list">
                        <div class="list_inner">'. $html. '</div>
                    </div>';
        }
    } catch (Exception $e) {
        return false;
    }
}

上面有5个地方需要修改称自己的,我已经标记出来了。搜索“你的网站域名”有3个,修改成你的网站地址;搜索“/第一步解压缩你的API物理路径/”,修改成你的真实网站物理目录地址,如/wwwroot/www.xxx.com/,这个需要你自己确定一下每个站都不一样。

Comments | 6 条评论
  • 沉沦

    Safari 18 Safari 18 iPad iOS 18.0.1 iPad iOS 18.0.1 1中国–河北–保定 联通 ip address 101.19.*.*

    感觉这个主题的代码少不了,功能有点多

    • 似水流年

      Google Chrome 93 Google Chrome 93 GNU/Linux GNU/Linux 1中国 中国联通 ip address 2408:8220:5f13:dc90:*:*

      已经添加不少功能了,我感觉比着原版就是PRO版本了。😎

  • obaby

    Google Chrome 126 Google Chrome 126 Mac OS X 10.15 Mac OS X 10.15 1中国–山东–青岛 联通 ip address 112.224.*.*

    代码好长。

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国 中国联通 ip address 2408:8220:5f13:dc90:*:*

      这个代码等于是把前两篇1和2的都包括了。

  • 刘郎

    Google Chrome 127 Google Chrome 127 GNU/Linux GNU/Linux 1中国–贵州–贵阳 移动 ip address 117.187.*.*

    js代码多了这样会不会拖垮网站速度呢😂

    • 似水流年

      IBrowse r IBrowse r Android 12 Android 12 1中国 中国联通 ip address 2408:8220:5f13:dc90:*:*

      我觉得还能接受。😹

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

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