巧用ChatGPT改造代码 让PIX主题片刻同时支持本地链接和外部链接转化为卡片
本文是《技术相关(共39篇)》目录的第 4 篇。阅读本文前,建议先阅读本文前3篇文章:
本代码已经升级:
改造代码最开始的目的是看到其他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注意事项在卡片页面已经做了提示。
三、改造过程:
涉及到以下文件:
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
四、改造效果:
彩蛋:如果觉得以上卡片宽度太窄,要和下面的点赞分享评论一样宽,只需要调整pix/inc/assets/css/main.css里的代码。
查找一下代码,大概在4326行:
.moment_card_item {
width: 100%;
max-width: 500px;
position: relative;
margin-bottom: 5px;
}
把max-width的值由原300px改为500px即可。
改造到此结束,用到的文件:
https://www.123pan.com/s/bqeA-kmj1H.html
提取码:V4Xr
您已阅读完《技术相关(共39篇)》目录的第 4 篇。请继续阅读本文后3篇文章:
麦涛
本来想在博客生成你这篇文章的卡片的,生成以后整个网站每次打开都好卡,只能想撤下了。😂
似水流年
这个看原网站的打开速度,并且有很大的几率生成不了卡片。