wordpress 多站点文章同步发布多技术探讨

news/2024/7/8 1:12:00

目标:单独同后台、同步发布到各个站点、包括自动上传图片、最好能兼容最新的区块模板(难度高)

方案一:使用wordpress插件

比较流行的有:Multisite Post Duplicator 、WP Multisite Content Copier、MultiSite Clone Duplicator、Syndicate Press、WordPressXMLRPCTools

Evernote Sync:关于WordPress插件Evernote Sync同步文章到wordpress站点的机制 – Devin

缺点:会加重wordpress、减慢运行速度

优点:不用考虑图片上传、区块模板问题

方案二:使用 Jetpack 插件提供的公共发言 API

1、在 Jetpack 管理面板中,启用公共发言 API。这需要您将 Jetpack 连接到 WordPress.com 帐户,并为您的站点启用公共发言 API 权限。
2、获取 API 密钥。您可以在 Jetpack 管理面板中找到它。
3、在要同步文章的站点中安装并启用 Jetpack 插件。
4、在这些站点中,使用以下代码向您的主站点发送请求以同步文章:

function my_sync_function($post_id) {
$post_data = get_post($post_id, ARRAY_A);
$post_data['post_password'] = 'mypassword'; // 如果需要设置文章密码,可以在此处设置
$post_data['post_type'] = 'post'; // 文章类型
$post_data['post_status'] = 'publish'; // 文章状态

$url = 'https://yoursite.wordpress.com/wp-json/wp/v2/posts'; // 主站点的公共发言 API URL
$api_key = 'your_api_key'; // 您的 Jetpack 公共发言 API 密钥

$args = array(
'body' => json_encode($post_data),
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json',
),
'method' => 'POST',
);

wp_remote_post($url, $args); // 向主站点发送 POST 请求
}
add_action('publish_post', 'my_sync_function'); // 将此函数绑定到“发布文章”动作

5、替换 $url 和 $api_key 变量的值。$url 应该是您的主站点的公共发言 API URL,$api_key 应该是您在第 2 步中获取的 Jetpack 公共发言 API 密钥。
6、将此代码添加到您的主题的 functions.php 文件中。
7、在任何要同步文章的站点上发布文章。文章将自动同步到您的主站点。如果您有多个要同步的站点,请重复步骤 3 到 6。

优点:还没有测试

缺点:加重wordpress的插件、减慢运行速度

方案三:通过XML-RPC方式

1、网站A(自动发布网站设置):远程发布的设置可能隐藏,所以先安装Control XML-RPC publishing,然后在”设置”->”撰写”里面开启远程发布

2、网站B(手动发布网站设置):安装插件 Syndicate Out 并设置好网站A的首页地址,后台用户名密码

这样在网站B里面发布的文章就会被自动同步到网站A里面了。
神奇的是,两个博客主题不同,上传的图片也自动同步过去了;
也有遗憾,以前发布的文章不会自动同步,新发布的文章才会在另一个服务器发布。

方案四:用代码实现

思路:在副网站创建API,API 利用wp_insert_post()函数来创建文章。主网站用cURL模拟 POST 请求副网站的API。支持同步文章标题、内容、类型、分类、标签,分类需要另一个站点也有创建相同名称的分类,别名和ID不需要相同。

在副博客站点的根目录创建一个文件,命名为xxxxxxxx-post.php,代码如下:并设置用于启动 API 的 key

<?php
/*
文章发表后同步到另一个站点(接收)
*/
define('WP_USE_THEMES', false);
require_once("wp-load.php");
$key='xxxxxxxxxx'; //设置API的密钥,建议设置复杂
if($_POST['key']==$key){
    $categorys=explode(',',$_POST['category']);
    $category=array();
    for($x=1;$x<count($categorys);$x++) {
     $category[$x-1]=get_cat_ID($categorys[$x]);
    }
        $info = array(
        'post_title' => $_POST['title'],
        'post_content' => $_POST['content'],
        'post_status' => 'publish',
        'post_author' => 1, //发布文章的作者ID,1 为管理员
        'post_date' => $_POST['date'],
        'tags_input' => $_POST['tags'],
        'post_category' => $category,
        'post_type' => $_POST['type']
        );
        wp_insert_post( $info );
}
?>

在主博客主题的functions.php文件的最后一个?>前加入已下代码,并设置 key,修改 API 地址

/*
文章发表后同步到另一个站点(发送)
*/
add_action('publish_post', 'E_sync_post'); //钩子,在文章发布时执行
function E_sync_post($post_ID) {
    $key='xxxxxxxxxxxxx'; //输入你设置的密钥
    $url='http://xxxxxx/xxxxxxxxxxxx-post.php';//API地址(接受同步文章博客地址,例:xx表示为发布文章主博客,那填写API地址就是负博客地址)
    $post_info = get_post($post_ID);
    if ( $post_info->post_status == 'publish' && $_POST['original_post_status'] != 'publish' ) {
        $title=$_POST['post_title'];
        $content=$_POST['content'];
                $date=$_POST['aa'].'-'.$_POST['mm'].'-'.$_POST['jj'].' '.$_POST['hh'].':'.$_POST['mn'].':'.$_POST['ss'];
                $category='';
                for($x=1;$x<count($_POST['post_category']);$x++) {
          $category.=','.get_cat_name($_POST['post_category'][$x]);
        }
        $type=$_POST['post_type'];
        $tags=str_replace('、',',',$_POST['tax_input']['post_tag']);
                if($_POST['newtag']['post_tag']){
                        $tags.=','.str_replace('、',',',$_POST['newtag']['post_tag']);
                }
        $data = 'key='.$key.'&title='.$title.'&content='.$content.'&date='.$date.'&category='.$category.'&type='.$type.'&tags='.$tags;
        $ch = curl_init (); //cURL模拟POST
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE );
        curl_setopt ( $ch, CURLOPT_POST, TRUE );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        $ret = curl_exec ( $ch );
        curl_close ( $ch );
        return $ret;
   }
}

这样一来,在主站发表一篇文章后,镜像站点也就会发表出来一篇文章了,但也会有一些意外情况,比如不是马上发表出来,而是显示计划中,正常隔几分钟后会发表好,但也会有发表失败,需要在后台文章管理中,选择该发表失败文章,状态修改为已发布,更新即可。

问题 1,由于主题升级后,functions.php 代码会被置换。用以上方法实现的内容镜像每次在主题升级后都需要修改 functions.php 代码,这会造成麻烦。 所以有如下解决办法,代码如下:

<?php
//文章推送
add_action('publish_post', 'fanly_sync_post'); //钩子,在文章发布时执行 
function fanly_sync_post($post_ID) { 
$key='123456'; //输入你设置的密钥 
$url='http://6.3838521.com/post.php';//API 地址,就是接受数据的那个站点
$post_info = get_post($post_ID); 
if ( $post_info->post_status == 'publish' && $_POST['original_post_status'] != 'publish' ) { 
$title=$_POST['post_title']; 
$content=$_POST['content']; 
$date=$_POST['aa'].'-'.$_POST['mm'].'-'.$_POST['jj'].' '.$_POST['hh'].':'.$_POST['mn'].':'.$_POST['ss']; 
$category=''; 
for($x=1;$x<count($_POST['post_category']);$x++) { 
$category.=','.get_cat_name($_POST['post_category'][$x]); 
} 
$type=$_POST['post_type']; 
$tags=str_replace('、',',',$_POST['tax_input']['post_tag']); 
if($_POST['newtag']['post_tag']){ 
$tags.=','.str_replace('、',',',$_POST['newtag']['post_tag']); 
} 
$data = 'key='.$key.'&title='.$title.'&content='.$content.'&date='.$date.'&category='.$category.'&type='.$type.'&tags='.$tags; 
$ch = curl_init (); //cURL 模拟 POST 
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE ); 
curl_setopt ( $ch, CURLOPT_POST, TRUE ); 
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); 
curl_setopt ( $ch, CURLOPT_URL, $url ); 
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
$ret = curl_exec ( $ch ); 
curl_close ( $ch ); 
return $ret; 
} 
}
?>

复制上面的代码,最好是用 Notepad ++等工具另存为 php 文件,打包成 zip 文档,在 wordpress 插件安装后台上传,安装并启用。

这样就是一个插件形式存在了,主题升级后不再有影响。

问题 2,有些主题编辑器是支持密码可见付费可见等短代码的,但短代码在编辑模式跟输出模式是不一样的,到了镜像站的内容会是输出模式,有可能会输出异常。

我的解决办法也是采用小插件的办法,对这些代码进行一个自动修改。代码如下:

<?php
//内容文字替换
function wpdaxue_replace_text($text){
$replace = array(
// '原始文字' => '替换为这些'
'\"20\"]' => '"20"]',
'\"10\"]' => '"10"]',
'\"50\"]' => '"50"]'
);
$text = str_replace(array_keys($replace), $replace, $text);
return $text;
}
add_filter('the_content', 'wpdaxue_replace_text'); //正文
add_filter('the_excerpt', 'wpdaxue_replace_text'); //摘要
add_filter('comment_text', 'wpdaxue_replace_text'); //评论
?>

问题3:图片处理问题,只是参考代码

function post_to_sina_weibo($post_ID) {

   /* 此处修改为通过文章自定义栏目来判断是否同步 */
   if(get_post_meta($post_ID,'weibo_sync',true) == 1) return;

   $get_post_info = get_post($post_ID);
   $get_post_centent = get_post($post_ID)->post_content;
   $get_post_title = get_post($post_ID)->post_title;
   if ($get_post_info->post_status == 'publish' && $_POST['original_post_status'] != 'publish') {
       $appkey='上个步骤获取的App key';  
       $username='用户名';
       $userpassword='密码';
       $request = new WP_Http;
       $keywords = ""; 

       /* 获取文章标签关键词 */
       $tags = wp_get_post_tags($post_ID);
       foreach ($tags as $tag ) {
          $keywords = $keywords.'#'.$tag->name."#";
       }

      /* 修改了下风格,并添加文章关键词作为微博话题,提高与其他相关微博的关联率 */
     $string1 = '【文章发布】' . strip_tags( $get_post_title ).':';
     $string2 = $keywords.' 查看全文:'.get_permalink($post_ID);

     /* 微博字数控制,避免超标同步失败 */
     $wb_num = (138 - WeiboLength($string1.$string2))*2;
     $status = $string1.mb_strimwidth(strip_tags( apply_filters('the_content', $get_post_centent)),0, $wb_num,'...').$string2;
     
		if ( has_post_thumbnail()) {   
			$timthumb_src = wp_get_attachment_image_src( get_post_thumbnail_id($post_ID), 'full' ); 
			$url = $timthumb_src[0]; 
		} else {
			preg_match_all('/<img.*?(?: |\\t|\\r|\\n)?src=[\'"]?(.+?)[\'"]?(?:(?: |\\t|\\r|\\n)+.*?)?>/sim', $get_post_centent,	$strResult, PREG_PATTERN_ORDER);  //正则获取文章中第一张图片
			$n = count($strResult[1]);  
			if($n > 0){
				$url=$strResult[1][0];  
			}
		}
	   /* 判断是否存在图片,定义不同的接口 */
       if(!empty($url)){
           $api_url = 'https://api.weibo.com/2/statuses/upload_url_text.json'; /* 新的API接口地址 */
           $body = array('status' => $status,'source' => $appkey,'url' => $url);
       } else {
           $api_url = 'https://api.weibo.com/2/statuses/update.json';
           $body = array('status' => $status,'source' => $appkey);
       }
       $headers = array('Authorization' => 'Basic ' . base64_encode("$username:$userpassword"));
       $result = $request->post($api_url, array('body' => $body,'headers' => $headers));

       /* 若同步成功,则给新增自定义栏目weibo_sync,避免以后更新文章重复同步 */
       add_post_meta($post_ID, 'weibo_sync', 1, true);
    }
}
add_action('publish_post', 'post_to_sina_weibo', 0);

/*
//获取微博字符长度函数 
*/
function WeiboLength($str)
{
    $arr = arr_split_zh($str);   //先将字符串分割到数组中
    foreach ($arr as $v){
        $temp = ord($v);        //转换为ASCII码
        if ($temp > 0 && $temp < 127) {
            $len = $len+0.5;
        }else{
            $len ++;
        }
    }
    return ceil($len);        //加一取整
}
/*
//拆分字符串函数,只支持 gb2312编码  
//参考:http://u-czh.iteye.com/blog/1565858
*/
function arr_split_zh($tempaddtext){
    $tempaddtext = iconv("UTF-8", "GBK//IGNORE", $tempaddtext);
    $cind = 0;
    $arr_cont=array();
    for($i=0;$i<strlen($tempaddtext);$i++)
    {
        if(strlen(substr($tempaddtext,$cind,1)) > 0){
            if(ord(substr($tempaddtext,$cind,1)) < 0xA1 ){ //如果为英文则取1个字节
                array_push($arr_cont,substr($tempaddtext,$cind,1));
                $cind++;
            }else{
                array_push($arr_cont,substr($tempaddtext,$cind,2));
                $cind+=2;
            }
        }
    }
    foreach ($arr_cont as &$row)
    {
        $row=iconv("gb2312","UTF-8",$row);
    }
    return $arr_cont;
}

参考网址:

WordPress文章发布后自动同步wordpress,无需插件API_wordpress数据库文章同步_云博客-资源宝的博客-CSDN博客

wordpress免登录Api文章发布接口_wordpress发布接口_乐编小易的博客-CSDN博客

集自动发布、本地管理于一身:基于 WordPress 同步的博客管理方案分享 - 少数派


http://lihuaxi.xjx100.cn/news/1066630.html

相关文章

#学习总结 C语言编程规范

养成一套正确的编程习惯&#xff0c;对职业发展尤为重要。出来参加工作之后&#xff0c;发现公司都有一套程序模板和各种命名规范&#xff0c;在此总结一下个人日常的C语言编程规范。每个人的要求和编程习惯可能都有所不同&#xff0c;仅供学习参考。 文章目录 前言一、头文件1…

cgroup配合tc工具对进程的上下行(出口入口)速度进行限制,附测试脚本

在开始之前&#xff0c;如果不熟悉cgroup、tc、以及ifb虚拟网卡&#xff0c;建议先了解一下再进行试验 注&#xff1a;为什么会用到ifb虚拟网卡呢&#xff0c;因为Linux自带的tc是一套控发不控收的框架。具体ifb详细原理&#xff0c;自行研究&#xff0c;网上资料多的很。 对出…

【Python | 基础语法篇】01、字面量、注释、变量、数据类型及转换

目录 一、字面量 1.1 什么是字面量 1.2 常用的值类型 1.3 字符串 1.4 如何在代码中写它们 1.5 总结 二、注释 2.1 注释的作用 2.2 注释的分类 2.3 注释实战 2.4 总结 2.5 思考 三、变量 3.1 什么是变量 3.2 案例——模拟钱包 3.3 变量的特征 3.4 思考 3.5 …

欧几里得算法、扩展欧几里得算法(特解、应用、通解)

文章目录 1. 欧几里得算法&#xff08;也叫辗转相除法&#xff09;1.1 直接上模拟1.2 几何理解1.3 用代数方法证明 g c d ( a , b ) g c d ( b , a % b ) gcd(a, b) gcd(b, a \% b) gcd(a,b)gcd(b,a%b)1.3.1 左推右&#xff1a; g c d ( a , b ) g c d ( b , a % b ) gcd(a…

2023年制造业产品经理NPDP认证报名找弘博创新

产品经理国际资格认证NPDP是新产品开发方面的认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会&#xff08;PDMA&#xff09;成立于1979年&#xff0c;是…

IDEA执行main方法的时候,会编译整个项目的问题

​ 今天遇到一个奇怪的问题&#xff0c;执行main方法会构建整个项目&#xff0c;速度奇慢无比。我就执行个main方法&#xff0c;搞这么复杂干嘛&#xff1f;经过查阅网上的攻略&#xff0c;最终找到解决方法。 以下方法适用于idea版本 问题解决方法&#xff1a; 参考 https://…

【脚本笔记】EditorApplication

EditorApplication 是编辑器下的主要程序类&#xff0c;为我们提供丰富的方法和事件等。 静态变量 applicationContentsPath 返回你当前Unity编辑器的Data文件路径。如D:/UnityVersions/2021.3.22f1c1/Editor/Data applicationPath 返回你当前Unity编辑器的执行文件位置。如…

五种原因导致孩子易患口腔溃疡,专家为你一一支招

最近&#xff0c;常接到电话咨询&#xff1a;疫情期间&#xff0c;孩子宅在家&#xff0c;反复起“口疮”怎么办&#xff1f; 这里说到的“口疮”&#xff0c;即是一种常见的口腔黏膜疾病——口腔溃疡。口腔溃疡的发病率较高&#xff0c;不仅成年人可能患病&#xff0c;不少儿…