WP2OSC–WordPress博客文章导入OSChina博客

By | 2015年7月2日

前言

OSChina的API开放至今都没用它做过什么事,如今建了个本站,正打算把文章内容备份到OSChina,官方提供了个导入工具(move.oschina.net),但是无法兼容目前新版的WP,它使用的是wp导出的xml文件。既然如此,何不自己使用API做一个导入工具呢?!

于是,wp2osc诞生了…

wp2osc概述

WP2OSC是一个可以把Wordpress博客的文章有选择的导入OSChina的博客中。

WP2OSC使用纯php代码,结合Wordpress自身的函数来读取文章列表、分类信息,准确率高,速度快,对Wordpress熟悉的同学还可以重新定制下页面显示方式。

wp2osc的导入方式

  1. 先登录OSCChina,拿到access_token后,回到index.php,token等信息使用session保存;
  2. 按照Wordpress的分类结构显示文章列表,然后在这个分类上,可以选择OSChina博客的系统分类和用户分类;
  3. 通过checkbox的方式,选择需要导入的文章。点击开始导入按钮后,程序自动组合当前勾选的文章的ID和对应的分类ID,拼接成json字符串,post给wp2osc.php文件;
  4. wp2osc.php文件根据文章ID,查询文章的各种信息,然后组合成最终的请求链接,post给OSChina Open API指定的URL上。

使用方法

访问我的git仓库,下载源码:https://git.oschina.net/lijialong1314/WP2OSC

  1. 下载文件后,把app目录放到wordpress站点的根目录;
  2. 打开app/wp2osc/index.php文件,修改第61行(您自己的oschina用户ID);
  3. 打开app/wp2osc/wp2osc.php文件,修改第9行(您自己的oschina用户ID);
  4. 打开app/wp2osc/token.php文件,修改第8,9,10行(您自己的APPkey,Secret,回调url需要设置为token.php文件在线上访问的完整路径);
  5. 访问 http://您的域名/app/wp2osc。

效果预览:http://devonios.com/app/wp2osc

存在的问题

由于OSChina的OpenAPI在处理content参数时,过滤了img标签,所以导入的文章无法显示图片。。。 详见:使用OpenApi导入Wordpress的博客内容时,图片地址如何处理?

目前只能手动复制图片源地址,然后粘贴到oschina的博客编辑器中,保存时,oschina会自动下载图片保存到自己的服务器上。

代码(1)获取Token

OSChina的API同样基于OAuth2(真是腻了…),需要先GET Code,然后用Code去Get Token。

我的做法是:在一个叫token.php的文件中,检测是否有code参数,如果没有就跳转到oschina的验证页面,登录成功后,oschina会跳回token.php页面,此时有了code参数,那就可以用它去请求获取token了,拿到token后,就可以把它保存在session中,然后再跳到程序的首页(index.php)。

<?php
session_start();
require("../lib/common.php");

$dataType = "json";
$response_type = "code";
$grant_type = "authorization_code";
$client_id = "您的app key";
$client_secret = "您的app secret";
//回调地址,需要设置为当前token.php文件在线上访问的完整路径
$redirect_uri = "http://devonios.com/app/wp2osc/token.php";
$codeurl = "https://www.oschina.net/action/oauth2/authorize";
$tokenurl = "https://www.oschina.net/action/openapi/token?";
$userurl = "https://www.oschina.net/action/openapi/user";
$cateurl = "https://www.oschina.net/action/openapi/blog_catalog_list";

$code = $_GET["code"];

if ($code != "")
{
   //获取token数据
}
else
{
  header("Location: ".$codeurl."?response_type=".$response_type."&client_id=".$client_id."&redirect_uri=".$redirect_uri);
}

获取token数据部分代码:

//请求的参数数组
$fields = [
  "grant_type" => urlencode($grant_type),
  "client_id" => urlencode($client_id),
  "redirect_uri" => urlencode($redirect_uri),
  "code" => urlencode($code),
  "state" => urlencode($state),
  "client_secret" => urlencode($client_secret),
  "dataType" => urlencode($dataType)
];

//转换成字符串
$fields_string = "";
foreach($fields as $key=>$value) {
 $fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');

//发送请求获取json数据

//拿到数据后,保存到session中
$_SESSION["osctoken"] = $token;
$_SESSION["oscusername"] = $username;
$_SESSION["oscuserid"] = $userid;
$_SESSION["syscate"] = $blog_sys_catalog_listArray;
$_SESSION["usercate"] = $blog_user_catalog_listArray;
//然后回到首页
header("Location: index.php");

代码(2)读取Wordpress的分类和文章

当回到index.php后,需要在页面显示文章列表,这里是用分类结构来显示的,即先读分类,然后用分类ID去读该分类下的所有文章。循环用列表方式(li)显示。

global $wpdb;
$request = "SELECT $wpdb->terms.term_id, name FROM $wpdb->terms ";
$request .= " LEFT JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_id = $wpdb->terms.term_id ";
$request .= " WHERE $wpdb->term_taxonomy.taxonomy = 'category' ";
$request .= " ORDER BY term_id asc";
$categorys = $wpdb->get_results($request);
//循环每个分类
foreach ($categorys as $category)
{
	$catname = $category->name;
	$catid = $category->term_id;
        //这里显示html代码
        //通过分类id,查询分类下的所有文章
        $catposts = new WP_Query();
        $catposts->query('cat='.$catid);
        while ($catposts->have_posts()) : $catposts->the_post();
        //这里显示html代码
        endwhile;
}

代码(3)根据文章ID获取文章详细信息(内容、标题、标签等)

在我们准备提交数据时,需要先通过选择的文章id获取文章的相关信息。

foreach($postidsobj as $postid)
{
	//一篇文章对象,使用wp提供的get_post函数
	$_post = get_post($postid);

	//内容
	$content = $_post->post_content;

	//将内容中的代码pre标签的class转换为oschina支持的
	$content = convert_pre_to_oscpre($content);

	//文章内容底部插入一些固定信息
	$content = insert_footinfo_content($content,$_post->post_name);

	//标题
	$title = $_post->post_title;

	//摘要,截取200字符
	$length = apply_filters('excerpt_length',200);
	$abstracts= apply_filters('the_excerpt',wp_trim_words($content,$length));

	//标签,用wp提供的wp_get_post_tags函数,转换成逗号分割的字符串
	$tags = wp_get_post_tags($postid);
	$_tags = "";
	foreach($tags as $tag){
		$_tags .= ($tag->name.",");
	}
	rtrim($_tags, ',');

	$postdata["catalog"] = $usercateid;
	$postdata["classification"] = $syscateid;
	$postdata["content"] = $content;
	$postdata["title"] = $title;
	$postdata["abstracts"]= preg_replace("/<(.*?)>/","",$abstracts);//摘要内容去掉html代码,oschina博客的摘要是纯文本形式
	$postdata["tags"] = $_tags;

	$resultJson = send_post($posturl,$postdata);
	$resultJsonObj = json_decode($resultJson,true);
	//结果保存下来
	$allresult[] =  "文章ID:".$postid.",文章标题:".$title.",状态:".$resultJsonObj["error_description"];
}

代码(4)转换pre代码标签

由于两边的代码高亮用的不是同一个插件,所以需要修改pre标签,这个需要根据您所用的编辑器,所用的代码高亮插件来调整。

我的代码如下:

function convert_pre_to_oscpre($content){

	$repArray = [
		'class="prettyprint"'           => 'class="brush:cpp;"',
		'class="prettyprint lang-php"'  => 'class="brush:php;"',
		'class="prettyprint lang-cpp"'  => 'class="brush:cpp;"',
		'class="prettyprint lang-bsh"'  => 'class="brush:shell;"',
		'class="prettyprint lang-js"'   => 'class="brush:js;"',
		'class="prettyprint lang-css"'  => 'class="brush:css;"',
		'class="prettyprint lang-html"' => 'class="brush:html;"'
	];

	foreach($repArray as $key=>$value){
		$content = str_replace($key,$value,$content);
	}

	return $content;
}

代码(5)php发送get和post请求

很简单,使用curl即可。

function send_get($urlstring)
{
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $urlstring);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$result = curl_exec($ch);
	curl_close($ch);
	return $result;
}

function send_post($urlstring,$data)
{
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_URL, $urlstring);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

	$result  = curl_exec($ch);
	curl_close($ch);
	return $result;
}

界面效果图

导入结束,显示结果: