关联的数据表

在phpBB3中导入用户时, 需要处理的有两张表, 一个是 topics, 一个是 posts.
为了方便与原数据关联, 需要在这两个表上新增一个字段并建立唯一索引

ALTER TABLE `topics` ADD COLUMN `ori_id` VARCHAR(32) NOT NULL DEFAULT '' AFTER `poll_vote_change`;
ALTER TABLE `posts` ADD COLUMN `ori_id` VARCHAR(32) NOT NULL DEFAULT '' AFTER `post_edit_locked`;
ALTER TABLE `topics` ADD UNIQUE INDEX `ori_id` USING BTREE (`ori_id`);
ALTER TABLE `posts` ADD UNIQUE INDEX `ori_id` USING BTREE (`ori_id`);

如果是新安装的论坛, 在每次导入之前, 用以下语句初始化:

TRUNCATE `topics`;
TRUNCATE `posts`;

需要的最小数据集

posts表, 需要的最小字段集为 `topic_id`, `forum_id`, `poster_id`, `poster_ip`, `post_time`, `enable_sig`, `post_username`, `post_subject`, `post_text`, `post_checksum`, `post_attachment`, `ori_id`
topics表, 需要的最小字段集为 `forum_id`, `topic_title`, `topic_time`, `ori_id`

导入topic和post时的处理逻辑
按创建时间将post正序排列后, 依次处理: 检查是否是topic的第一篇, 如果是则创建topic, 如果不是则去查找(目标db, 源db, 如果找不的第一篇时, 需要将自己设为第一篇), 这样topicId确定后就可以写入post了, 然后再拿写入产生的postId, 去更新topic的信息

Python代码

子函数

import rbcommon
import re def getTopic(cursor, articleId):
sql = 'SELECT topic_id FROM phpbb_topics WHERE ori_id = %s'
cursor.execute(sql, (articleId))
row = cursor.fetchone()
if (row is not None):
return row['topic_id']
else:
return 0 def getAuthor(cursor, name):
sql = 'SELECT user_id FROM phpbb_users WHERE username_clean = %s'
cursor.execute(sql, (name.lower()))
row = cursor.fetchone()
if (row is not None):
return row['user_id']
else:
print('Not exists:{}'.format(name))
exit() def insertTopic(cursor, forum_id, topic_title, topic_time, ori_id):
sql = 'INSERT IGNORE INTO `phpbb_topics` (`forum_id`, `topic_title`, `topic_time`, `ori_id`) ' \
'VALUES (%s, %s, %s, %s)'
cursor.execute(sql, (forum_id, topic_title, topic_time, ori_id))
lastId = cursor.lastrowid
return lastId def insertPost(cursor, topic_id, forum_id, poster_id, poster_ip, post_time, post_username, post_subject, post_text, post_attachment, ori_id):
sql = 'INSERT IGNORE INTO `phpbb_posts` (`topic_id`, `forum_id`, `poster_id`, `poster_ip`, `post_time`, `enable_sig`, ' \
'`post_username`, `post_subject`, `post_text`, `post_checksum`, `post_attachment`, `ori_id`) ' \
'VALUES (%s, %s, %s, %s, %s, 0, %s, %s, %s, \'\', %s, %s)'
cursor.execute(sql, (topic_id, forum_id, poster_id, poster_ip, post_time, post_username, post_subject, post_text, post_attachment, ori_id))
lastId = cursor.lastrowid
if (lastId == 0):
print('Duplicate ID:>{}<'.format(ori_id))
return lastId def updateTopicFirst(cursor, authorId, postId, author, title, createdAt, topicId):
sql = 'UPDATE phpbb_topics SET ' \
'topic_poster=%s, topic_first_post_id=%s, topic_first_poster_name=%s, ' \
'topic_last_poster_id=%s, topic_last_post_id=%s, topic_last_poster_name=%s, topic_last_post_subject=%s, topic_last_post_time=%s WHERE `topic_id`=%s' cursor.execute(sql, (authorId, postId, author, authorId, postId, author, title, createdAt, topicId)) def updateTopic(cursor, authorId, postId, author, title, createdAt, topicId):
sql = 'UPDATE phpbb_topics SET topic_replies=topic_replies+1, topic_replies_real=topic_replies_real+1, ' \
'topic_last_poster_id=%s, topic_last_post_id=%s, topic_last_poster_name=%s, topic_last_post_subject=%s, topic_last_post_time=%s WHERE `topic_id`=%s'
cursor.execute(sql, (authorId, postId, author, title, createdAt, topicId))

主方法

tb_article_all = rbcommon.db['article_all']
limit = 1000
total = tb_article_all.estimated_document_count()
for i in range(0, total, limit):
print("\n" + '######## Start:' + str(i) + ', limit:' + str(limit) + ' ########')
articles = tb_article_all.find().sort('createdAt', 1).limit(limit).skip(i)
for article in articles:
# extract the forumId, author, etc
pos = article['_id'].find('.')
forumId = article['_id'][0:pos]
author = article['author'].strip()
posterIp = '' if (not 'ip' in article) else article['ip']
attachments = 0 if (len(article['attachments']) == 0) else 1
# content = article['content'].replace('\\n', '\n')
content = re.sub(r'\\n', '\n', article['content'])
content = re.sub(r'\\r\[[;\d]{0,8}m', '', content)
content = re.sub(r'\\(/|"|\')', r'\1', content) with rbcommon.mysqlclient.cursor() as cursor:
# get author Id
authorId = getAuthor(cursor, author) # Check if it is a topic
firstPostFlag = False
if (article['_id'] == article['parentId']):
firstPostFlag = True
# if yes, check if it exists
topicId = getTopic(cursor, article['_id'])
if (topicId == 0):
# if not, insert a topic, get the topicId
topicId = insertTopic(cursor, forumId, article['title'], article['createdAt'], article['_id'])
else:
# if not a topic, get the topic ID
topicId = getTopic(cursor, article['parentId'])
if (topicId == 0):
# if not exists, find it and insert it(topic record), and get the topic ID
dummy = tb_article_all.find_one({'_id': article['parentId']})
# if dummy not exists, make this post the first post
if (dummy is None):
dummy_title = article['title']
dummy_createdAt = article['createdAt']
dummy_author = article['author'].strip()
dummy_ori_id = article['parentId']
firstPostFlag = True
else:
dummy_title = dummy['title']
dummy_createdAt = dummy['createdAt']
dummy_author = dummy['author'].strip()
dummy_ori_id = dummy['_id']
topicId = insertTopic(cursor, forumId, dummy_title, dummy_createdAt, dummy_ori_id) # should not be 0 at this point
if (topicId == 0):
print('Failed to get topicId for {}'.format(article['_id']))
exit() # perform the actual post insert
postId = insertPost(cursor, topicId, forumId, authorId, posterIp, article['createdAt'], author, article['title'], content, attachments, article['_id'])
if (postId == 0):
print('Post already exists: {}'.format(article['_id']))
rbcommon.mysqlclient.rollback()
continue # update the topic
if (firstPostFlag):
updateTopicFirst(cursor, authorId, postId, author, article['title'], article['createdAt'], topicId)
else:
updateTopic(cursor, authorId, postId, author, article['title'], article['createdAt'], topicId) # commit all changes at last
rbcommon.mysqlclient.commit()

同步版面数据

导入结束后, 即使同步后台数据和清空缓存, 在前台也是看不到版面文章的, 显示都是空. 可以在后台的版面管理中, 点击版面右侧的同步图标, 对每个版面进行手动同步. 如果版面较多不合适手工处理, 则可以在论坛的根目录下, 创建下面这个脚本 tmp.php:

<?php
define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
echo 'Start';
sync('forum', '', '', false, true);
echo 'Done';
$cache->destroy('sql', FORUMS_TABLE);
?>

在命令行下执行命令 php tmp.php 版面的数据就全部同步了.

.

phpBB3导入帖子的Python脚本的更多相关文章

  1. phpBB3导入用户的Python脚本

    关联的数据表 在phpBB3中导入用户时, 需要处理的有两张表, 一个是 users, 一个是 user_group. 如果是新安装的论坛, 在每次导入之前, 用以下语句初始化: DELETE FRO ...

  2. phpBB3导入版面的Python脚本

    关联的数据表 在phpBB3中导入版面时, 需要处理的有两张表, 一个是 forums, 一个是 acl_groups. 如果是干净的论坛, 可以不保留安装时填入的默认分区和版面, 直接用以下语句初始 ...

  3. zabbix3.4用Python脚本Excel批量导入主机

    1.安装xlrd读取Excel文件 1.1. 下载setuptools-38.2.4.zip,上传至zabbix服务器解压安装,下载地址:https://pypi.python.org/package ...

  4. 某互联网后台自动化组合测试框架RF+Sikuli+Python脚本

    某互联网后台自动化组合测试框架RF+Sikuli+Python脚本 http://www.jianshu.com/p/b3e204c8651a 字数949 阅读323 评论1 喜欢0 一.**Robo ...

  5. 一句话爆破速度提升一千倍python脚本

    这个脚本是接地提供的思路,一句话爆破速度提升一千倍,看了他的帖子然而没有看到工具,思路很牛逼,我提供一个Python脚本本地测试了下,十万密码只需要3秒,速度还是可以的 # coding:utf-8 ...

  6. ArcGIS使用Python脚本工具

    在Pyhton写的一些代码,用户交互不方便,用户体验比较差,不方便重用.在ArcGIS中可以将用写的Python代码导入到ToolBox中,这样用起来就比较方便了.这里用按要素裁剪栅格的Python来 ...

  7. 用 Python 脚本实现对 Linux 服务器的监控

    目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具 比如 inotify-sync(文件系统安全监控软件).glances(资源监控工具)在实际工作中,Linux 系统 ...

  8. 使用Python脚本强化LLDB调试器

    LLDB是Xcode自带的调试器,作为一个iOS应用开发程序员,平时我在开发应用时会使用LLDB来调试代码.在逆向应用时,也会用到LLDB来跟踪应用的执行过程. LLDB还内置了一个Python解析器 ...

  9. 利用pyinstaller将python脚本打包发布

    之前写了一个小工具,将excel配置表转换为json.xml.lua等配置文件.最近在学习egret,正好需要转换配置文件,刚好就用上了.然而当我想把工具拷到工作目录时,就发愁了.之前我为了方便扩展, ...

随机推荐

  1. Lunch War with the Donkey CSU - 2084

    Jingze is a big figure in California State University for his stubbornness. Because of his new failu ...

  2. hdu 2181 哈密顿绕行世界问题【DFS】

    题目链接 题目大意: Problem Description 一个规则的实心十二面体,它的 20个顶点标出世界著名的20个城市,你从一个城市出发经过每个城市刚好一次后回到出发的城市.    Input ...

  3. Mybatis之延迟加载机制

    1.  延迟加载的含义: 用到的时候才会去进行相关操作 2.  延迟加载的例子: 2.1 spring的BeanFactory,在getBean()的时候才创建Bean 2.2 物理分页查询,只有点击 ...

  4. swap

    添加交换分区 SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后将把内存中暂时不常用的数据临时存放到硬盘中,以便腾出物理内存空间让更活跃的程序服务来使用的技术,其设计目的是为了解决真实物理 ...

  5. 分布式存储MooseFS

    MooseFS 简介 http://moosefs.org/ MFS特性 安装和配置简单方便   可靠性高(数据的多个拷贝被存储在多个不同的服务器上)   通过添加新的服务器或硬盘就可以实现容量的动态 ...

  6. BZOJ.4825.[AHOI/HNOI2017]单旋(线段树)

    BZOJ LOJ 洛谷 这题不难啊,我怎么就那么傻,拿随便一个节点去模拟.. 我们只需要能够维护,将最小值或最大值转到根.模拟一下发现,对于最小值,它的右子树深度不变(如果存在),其余节点深度全部\( ...

  7. Android应用的内存管理

    管理应用的内存可以分为两个部分内容: 1. 首先需要理解:How Android Manages App Processes and Memory Allocation? 2. 其次需要考虑:我们设计 ...

  8. IntelliJ IDEA无法更新maven索引

    maven索引的作用时在添加dependency的时候能有自动提示,不影响dependency的下载: 解决办法: 1.http://ju.outofmemory.cn/entry/359450 2. ...

  9. BZOJ4855 : [Jsoi2016]轻重路径

    首先用树状数组维护dfs序来快速支持一个点子树大小的询问. 每次删掉一个叶子时,从根开始往叶子走,显然只有$2size[x]\leq size[father]$的点的父亲才有可能换重儿子. 从根开始往 ...

  10. [P3452][POI2007]BIU-Offices (BFS)

    这里有一个很完美(搞笑但是确实是这样的)翻译 题意 神牛 LXX 昨天刚刚满 18 岁,他现在是个成熟的有为男青年.他有 N 个 MM,分别从 1 到 N 标号. 这些 MM 有些是互相认识的.现在, ...