搭建网站的工具和过程降到低门槛和低成本,WordPress使用小型文件数据库SQLite组建Sandbox系统模拟
朗读全文
Your browser does not support the audio element.
有什么用 创建工作室/公司网站, 网店; 发布文章, 分享经验等
SEO友好
展示: https://n.carlzeng.com
怎么用 1 2 3 4 5 6 7 8 9 10 11 version: '3' services: wordpress: image: soulteary/sqlite-wordpress restart: always ports: - 8104 :80 volumes: - ./:/var/www/html - /volume2/KingchuxingSSD512G/MacBookPro_Skitch/storage/app/uploads/2026/05:/var/www/html/wp-content/uploads/lskyupload202605
后来验证: 这种方式最后用于sandbox的建设, 因为网店再导入商品和图片后下单会报错, 切换使用官方版本后解决; 用这种轻量级的sandbox好处有: 随便安装插件等, 不怕污染了主数据库(数据的清理干净很麻烦, 耗时, 易出错)
演示/实践 https://w.carlzeng.com
相关内容
WooCommerce导入产品 安装插件: WebToffee Import Export
如何导入产品照片? 需求: 导入所有几千张照片, 然后关联到产出
WP的SQLlite数据库文件在哪里?
WordPress 用 SQLite 时(官方插件 sqlite-database-integration 或 wp-sqlite-db),数据库文件默认在:
1 wp-content/database/.ht.sqlite
最后图片还是要使用WP原始的图库功能;
上传到图库, 但由于兰空图床的目录使用的docker的映射方式, 被我直接映射到docker目录
/volume2/KingchuxingSSD512G/MacBookPro_Skitch/storage/app/uploads/2026/05
这样; Addd From Server Reloaded 就能加载到这些1170+张照片了
导入后: 图库
故障: 很多可以在兰空中看到的照片, 无法访问, 不知为何(是否和docker wordpress映射 并上传后有关? )https://img.carlzeng.com:3/i/2026/05/O1CN01bBq8Wx1smZl0yPj7B_!!4611686018427385985-53-fleamarket.jpg
O1CN01fP0ICM1smZqe9QMrt_!!4611686018427385985-53-xy_item.jpg
成功链接到使用免费版的WebToffee Import Export; 导入所有产品和相关联的图片(先导入到图库中)
照片可以导入格式: /wp-content/uploads/O1CN013Dpd011smZsfIaiIb_4611686018427385985-53-xy_item.jpg
可以导入多张照片, 用 , 空格分开
-5:09pm- 用,分隔即可
修改全部的csv文件, 转化
| 为 ,
!! 去除
格式如上
优化docker-compose 的目录映射 添加:ro, 确保兰空图床中的文件, 不要受影响/删除
导入详细商品目录 用DBeaver, 导入wp_posts表数据, 和 wp_postmeta表数据
绝大部分数据成功/轻松导入.
发现问题:
有的货品的SKU和价格丢失
修复步骤:
查询到sku 或 price为空的行, 一共60个; 复制出p.ID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 SELECT p.ID as product_id, p.post_title as product_name, sku.meta_value as sku, price.meta_value as price FROM wp_posts p LEFT JOIN wp_postmeta sku ON p.ID = sku.post_id AND sku.meta_key = '_sku' LEFT JOIN wp_postmeta price ON p.ID = price.post_id AND price.meta_key = '_price' WHERE p.post_type = 'product' AND p.post_status = 'publish' AND ( sku.meta_value IS NULL OR sku.meta_value = '' OR price.meta_value IS NULL OR price.meta_value = '' );
到Sandbox正常的数据库中提取这些wp_postmeta相关的行数据
1 2 3 4 5 6 7 8 SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (9, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338)
使用DBeaver导出这些数据, 然后目标选择到MariaDB的wp_postmeta 表,
注意: 不要输出meta_id, 列, 不然会存在PK冲突的问题, 导致数据无法正常导入
导入最后一步选择 Insert IGNORE
至此60个有显示故障的商品wp_postmeta被重新导入修复完毕!
下一步: 继续设置商品的分类和品牌, 标签等
解锁媒体库目前上传限制2MB 媒体库目前上传限制时2MB, 如何改成4M?
docker-compose中添加
1 2 3 4 WORDPRESS_CONFIG_EXTRA: | @ini_set( 'upload_max_filesize', '4M' ); @ini_set( 'post_max_size', '4M' ); @ini_set( 'max_execution_time', '300' );
无法解决问题, 媒体上传限制还是2M
1 2 @ini_set ( 'upload_max_size' , '4M' ); @ini_set ( 'post_max_size' , '4M' );
解决办法: 新建一个插件
1 2 3 4 5 6 7 8 9 <?php add_filter ( 'upload_size_limit' , 'b5f_increase_upload' );function b5f_increase_upload ( $bytes ) { return 4194304 ; }
把这个文件保存, 然后压缩成.zip文件; 比如: increase-upload-limit.zip
然后在安装插件页面 上传, 启用, 解决!
而且编辑是动态的, 也就是说 想要修改这个限制; 直接ssh过去服务器中, 修改这个值; 立即生效, 简单直接.
在wordpress 根目录 创建一个新的php.ini文件
使用代码或文本编辑器,将以下代码添加到现有或新的php.ini 文件中:
1 2 3 upload_max_filesize = 5M post_max_size = 5M memory_limit = 128M
本小节感谢: WordPress上传限制,最大上传文件大小,最大上传限制 文字教程
修改商店页面标题:
同时也添加到了vi increase-upload-limit.php 这个文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 add_filter ( 'document_title_parts' , function( $parts ) { if ( is_shop () || is_product_category () || is_product_tag () ) { if ( ! empty ( $parts ['title' ] ) ) { $parts ['title' ] = '案例 - ' . $parts ['title' ]; } else { $parts ['title' ] = '案例' ; } } return $parts ; }, 999 );
如何批量导入MD博客文章 插件: Import Markdown 似乎只能单独, 单个文件的导入?
各种研究, 最后在一个博主的站点上找到了解决方案, 用一个python脚本 一键批量上传目录中441篇文章到WordPress
简直太高效了, 分享源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 import os import sysimport sslssl._create_default_https_context = ssl._create_unverified_context """ 需要安装如下pip包 pip3 install python-frontmatter pip3 install markdown pip install 'Markdown' pip3 install python-wordpress-xmlrpc """ import frontmatterimport markdownfrom wordpress_xmlrpc import Client, WordPressPostfrom wordpress_xmlrpc.methods.posts import NewPostdef make_post (filepath, metadata ): """ make a WordPressPost for Client call :param filepath: 要发布的文件路径 :param metadata: 字典类型 包括 metadata['category']: 文章分类 metadata['tag']: 文章标签 metadata['status']: 有publish发布、draft草稿、private隐私状态可选 :return WordPressPost: if success None: if failure """ filename = os.path.basename(filepath) filename_suffix = filename.split('.' )[-1 ] filename_prefix = filename.replace('.' + filename_suffix, '' ) if filename_suffix != 'md' : return None post_from_file = frontmatter.load(filepath) post_content_html = markdown.markdown(post_from_file.content, extensions=['markdown.extensions.fenced_code' ]) post_content_html = post_content_html.encode("utf-8" ) metadata['title' ] = filename_prefix metadata_keys = metadata.keys() for key in metadata_keys: if key in post_from_file.metadata: metadata[key] = post_from_file.metadata[key] post = WordPressPost() post.content = post_content_html post.title = metadata['title' ] post.post_status = metadata['status' ] post.terms_names = { 'category' : metadata['category' ], 'post_tag' : metadata['tag' ] } post.comment_status = 'open' return post def push_post (post, client ): """ 上传post到WordPress网站 :param post: 要发布的文章(WordPressPost类型),由make_post函数得到 :param client: 客户端 :return True: if success """ return client.call(NewPost(post)) def get_filepaths (path ): """ 如果path是目录路径,递归遍历path目录下的所有文件,将所有文件路径存入filepaths 如果path是文件路径,直接将单个文件路径存入filepaths :param path: 你要上传的目录路径或文件路径(绝对路径) :return filepaths: 该目录下的所有子文件或单个文件的绝对路径 None: wrong path """ filepaths = [] if os.path.isdir(path): for now_dirpath, child_dirnames, child_filenames in os.walk(path): if 'secret' in now_dirpath.lower(): continue for filename in child_filenames: filepath = os.path.join(now_dirpath, filename) filepaths.append(filepath) filepaths.sort() return filepaths elif os.path.isfile(path): return [path] else : return None if __name__ == '__main__' : path = '/Users/carlzeng/App/blog/source/_posts' domain_list = [ 'https://wp.carlzeng.com:3/' ] username = '*******' password = '*******' for domain in domain_list: post_metadata = { 'category' : ['未分类' ], 'tag' : ['手柄一修哥' ], 'status' : 'publish' } print ('----------------------------------------------START----------------------------------------------' ) filepaths = get_filepaths(path) if filepaths is None : print ('FAILURE: wrong path' ) sys.exit(1 ) client = Client(domain + '/xmlrpc.php' , username, password) md_cnt = 0 all_cnt = len (filepaths) process_number = 0 failpaths = [] for filepath in filepaths: process_number = process_number + 1 filename = os.path.basename(filepath) try : post = make_post(filepath, post_metadata) if post is not None : push_post(post, client) md_cnt = md_cnt + 1 print ('Process number: %d/%d SUCCESS: Push "%s" completed!' % (process_number, all_cnt, filename)) else : failpaths.append(filepath) print ('Process number: %d/%d WARNING: Can\'t push "%s" because it\'s not Markdown file.' % ( process_number, all_cnt, filename)) except Exception as e: failpaths.append(filepath) print ('Process number: %d/%d ERROR: Failed to push "%s" | Reason: %s' % (process_number, all_cnt, filename, str (e))) print ('-----------------------------------------------END-----------------------------------------------' ) print ('SUCCESS: %d files have been pushed to {0}.' .format (domain) % md_cnt) if len (failpaths) > 0 : print ('WARNING: %d files haven\'t been pushed to {0}.' .format (domain) % len (failpaths)) print ('\nFailure to push these file paths:' ) for failpath in failpaths: print (failpath)
感谢作者: 一键上传markdown 格式文章到wordpress
修改的点有:
第137行 post = make_post(filepath, post_metadata) 这个需要try catch
添加排序功能: 目前加载目录下的文件没有排序, 请按文件的英文字母顺序排序
请排除目录名中包含secret的目录
运行后输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ----------------------------------------------START---------------------------------------------- Process number: 8/418 SUCCESS: Push "1099-MISC是什么-CarlZeng.md" completed! Process number: 9/418 SUCCESS: Push "A-feature-in-Netsuite-Reports-Financial-Balance-Sheet-CarlZeng.md" completed! Process number: 10/418 SUCCESS: Push "AI脸部识别,人脸比对,人脸识别-CarlZeng.md" completed! Process number: 11/418 SUCCESS: Push "AJAX提交数据时-中文处理-以及js-url-中文处理-CarlZeng.md" completed! Process number: 12/418 SUCCESS: Push "Bar-codes-in-NetSuite-Saved-Searches-transport-reprint-活用NetSuite搜索页面显示可扫描条码-CarlZeng.md" completed! ... Process number: 417/418 SUCCESS: Push "高手写出的是天使,而新手写的,可能是魔鬼!-Javascript这样的脚本语言,由于太灵活-CarlZeng.md" completed! Process number: 418/418 SUCCESS: Push "高效的服务端生成QRCODE二维码方案-Docker搭建.md" completed! -----------------------------------------------END----------------------------------------------- SUCCESS: 411 files have been pushed to https://wp.carlzeng.com:3/. WARNING: 7 files haven't been pushed to https://wp.carlzeng.com:3/. Failure to push these file paths: /Users/carlzeng/App/blog/source/_posts/.DS_Store
遇到的bug/enhancement:
手动完成文章所有分类,
标签和照片无法导入; (用python, 等待更新, 提取这些信息到WP)
下一步:
Woocommerce下单错误 点击下单报错:
1 Uncaught Error: Call to a member function get_total() on false in /var/www/html/wp-content/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php:314\nStack trace:\n#0 /var/www/html/wp-content/plugins/woocommerce/src/StoreApi/Legacy.php(56): WC_Gateway_COD->process_payment(4131)\n#1 /var/www/html/wp-includes/class-wp-hook.php(341): Automattic\\WooCommerce\\StoreApi\\Legacy->process_legacy_payment(Object(Automattic\\WooCommerce\\StoreApi\\Payments\\PaymentContext), Object(Automattic\\WooCommerce…wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters(NULL, Array)\n
wp_woocommerce_order_items 等等, 这些表都有的
为了解决woocommerce的故障, 需要让wordpress使用官方的docker image, 切换数据库(mssql, mariadb)方案
从另外一个wordpress数据库导入文章 通过工具链接到MariaDB, 将查询导出为CSV; 然后导入到在线的文件型数据库中: .ht.sqlite
1 2 3 4 5 6 7 8 9 10 SELECT p.* FROM wp_posts pJOIN wp_term_relationships tr ON p.ID = tr.object_idJOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_idWHERE tt.term_id = 22 AND tt.taxonomy = 'category' AND p.post_type = 'post' AND p.post_status = 'publish' ORDER BY p.post_date DESC ;
继续在新的系统中编辑这些文章
修改域名, 和导入的文章URL需要修改
1 2 3 4 5 6 7 8 9 10 11 SELECT 'wp_posts' AS src, CONCAT(ID,':' ,post_title) AS name, guid FROM wp_posts WHERE guid LIKE 'http%' UNION ALL SELECT 'wp_postmeta' AS src, meta_key, meta_value FROM wp_postmeta WHERE meta_value LIKE 'http%' ;
1 2 3 4 5 6 7 8 9 10 11 12 13 UPDATE wp_posts SET post_content=REPLACE(post_content,'http://192.168.6.203:8108','https://netsuite.carlzeng.com'), guid=REPLACE(guid,'http://192.168.6.203:8108','https://netsuite.carlzeng.com'); UPDATE wp_posts SET post_content=REPLACE(post_content,'https://w.carlzeng.com','https://netsuite.carlzeng.com'), guid=REPLACE(guid,'https://w.carlzeng.com','https://netsuite.carlzeng.com'); --手动更新了一行 -- 4. 文章自定义字段里的URL SELECT 'wp_postmeta' AS src, meta_key, meta_value, * FROM wp_postmeta WHERE meta_value LIKE 'http%';
如何修复错误 “Too Many Redirects” WordPress 报错 (ERR_TOO_MANY_REDIRECTS) ERR_TOO_MANY_REDIRECTS
使用本地部署后, 局域网可访问, 如: http://192.168.6 .* 那么NPM反代以后, 使用 https://wp.yourdomain.com:3/wp-admin可正常访问后台 ; 下一步: 如何让远程的CDN直接使用无需携带端口的访问方式?
首先要去处理的是本地访问
然后反向代理, 测试反向代理后的后台访问是否正常, css都正常, 登录也正常
确保CDN后者cloudflare中的映射是通的; 具体详见“博客迁移说明” CDN章节
//define(‘WP_HOME’,’https://w.carlzeng.com ‘); define(‘WP_SITEURL’,’https://w.carlzeng.com ‘);
#这个用来应急时调整, 获得后台的访问权限; 主要是要先把CDN那边端口映射先做好, 映射到本地的NPM 如: *.yourdomain.com:4443(这个端口目前只有后台的访问权限/wp-admin
切换到官方Docker Image Production生成环境
1 2 mkdir wordpresshtml && mkdir db vi docker-compose.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 services: wordpress: image: wordpress restart: always ports: - 8106 :80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: example user WORDPRESS_DB_PASSWORD: example pass WORDPRESS_DB_NAME: wordpress volumes: - ./wordpresshtml:/var/www/html db: image: mysql:8.0 restart: always environment: MYSQL_DATABASE: wordpress MYSQL_USER: example user MYSQL_PASSWORD: example pass MYSQL_RANDOM_ROOT_PASSWORD: '1' volumes: - ./db:/var/lib/mysql volumes: wordpress: db:
chown mysql /volume2/KingchuxingSSD512G/docker/compose/wordpress2/db -R
chmod +777 /volume2/KingchuxingSSD512G/docker/compose/wordpress2/db -R
chown mysql /volume2/KingchuxingSSD512G/docker/compose/wordpress2/wordpresshtml -R
chmod +777 /volume2/KingchuxingSSD512G/docker/compose/wordpress2/wordpresshtml -R
必须要运行这个目录权限, 否者就是各种报错.
woocommerce Connection Information
upload a WooCommerce .zip file and install the plugin on the local host. Every time I click install button, WordPress is asking for connection for FTP
Add this line in wp-config.php
1 define ( 'FS_METHOD' , 'direct' );
1 2 3 4 define ('WP_SITEURL' ,'https://w.carlzeng.com' ); define ('WP_CONTENT_URL' , '/wp-content' );
还是决定切换到MariaDB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 services: wordpress: image: wordpress restart: always ports: - 8106 :80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: example user WORDPRESS_DB_PASSWORD: example pass WORDPRESS_DB_NAME: wordpress volumes: - ./wordpresshtml:/var/www/html db: image: mariadb:jammy restart: always ports: - 8107 :3306 environment: MYSQL_DATABASE: wordpress MYSQL_USER: example user MYSQL_PASSWORD: example pass MYSQL_RANDOM_ROOT_PASSWORD: '1' volumes: - ./db:/var/lib/mysql volumes: wordpress: db:
初始化安装好wordpress, 只需要这些表:
手工导入wp_posts (直接从数据库到数据库)
然后用csv导入wp_postmeta
裁剪您的图片时发生错误。
原来是操作不了PNG; JPG可以的, 无所谓, 无伤大雅
SQL修复文章分类 wp_term_taxonomy 这个基础表维护的是: 分类ID和分类名称; 比如: 产品分类、文章分类、产品类型、模版类型部分区域
wp_term_relationships 这个表保存文章/产品 与分类的关系; 比如: 文章#1属于类名#1
步骤一: 插入wp_term_relationships 1 2 3 INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id, term_order) select ID, 22, 0 from wp_posts where post_type = 'post' and post_content like '%netsuite%' or post_title like '%netsuite'
note: 用IGNORE支持多次执行, 会避开重复的行, 输出
1 2 3 4 5 6 7 Duplicate entry '205-22' for key 'PRIMARY' Duplicate entry '3298-22' for key 'PRIMARY' Duplicate entry '3306-22' for key 'PRIMARY' Duplicate entry '3312-22' for key 'PRIMARY' Duplicate entry '3640-22' for key 'PRIMARY' Duplicate entry '3662-22' for key 'PRIMARY'
步骤二: 插入wp_term_taxonomy 1 2 3 4 5 6 7 8 #关键后续:更新 WordPress 分类计数器 UPDATE wp_term_taxonomy SET count = ( SELECT COUNT(*) FROM wp_term_relationships WHERE wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id ) WHERE term_taxonomy_id = 22
添加剩余的文章都分类到: 一修哥工作室
1 2 3 4 5 6 7 8 9 10 11 12 INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id, term_order)select ID, 23 , 0 from wp_posts where post_type = 'post' and ID not in (select object_id from wp_term_relationships) UPDATE wp_term_taxonomy SET count = ( SELECT COUNT (* ) FROM wp_term_relationships WHERE wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id ) WHERE term_taxonomy_id = 23
导入部分硬件工作记录/成功案例 以准备好成功案例的md聊天记录导出, 导入展现. 此md来源为: 闲鱼APP中聊天记录导出
批量, 加载目录下md文件时, 需要按md文件的创建时间顺序来加载
Sanbox测试得知: 待修复 视频,如何支持在线点击查看? md文件中如何显示视频播放器?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import osimport repattern = r'\[\s*视频\s*\]\(\s*(https?://[^\s\)]+|[^\s\)]+\.mp4|[^\s\)]+)\s*\)' def get_file_creation_time (file_path ): """兼容多系统的获取文件创建时间函数""" stat = os.stat(file_path) try : return stat.st_birthtime except AttributeError: return stat.st_ctime def convert_md_files_by_order (): current_dir = os.getcwd() md_files = [f for f in os.listdir(current_dir) if f.endswith(".md" )] md_files.sort(key=lambda x: get_file_creation_time(os.path.join(current_dir, x))) success_count = 0 print ("开始按创建时间【升序】处理文件...\n" + "-" * 40 ) for filename in md_files: file_path = os.path.join(current_dir, filename) with open (file_path, "r" , encoding="utf-8" ) as f: content = f.read() if re.search(pattern, content): replaced_content = re.sub( pattern, r"\n\n<video src='\1' controls width='100%' height='auto' loop='loop'></video>\n\n" , content, ) with open (file_path, "w" , encoding="utf-8" ) as f: f.write(replaced_content) c_time = get_file_creation_time(file_path) from datetime import datetime time_str = datetime.fromtimestamp(c_time).strftime( "%Y-%m-%d %H:%M:%S" ) print (f"[{time_str} ] 成功转换: {filename} " ) success_count += 1 print ("-" * 40 + f"\n处理完成!共依序转换了 {success_count} 个文件。" ) if __name__ == "__main__" : convert_md_files_by_order()
1 2 3 ----------------------------------------------START---------------------------------- Process number: 1/30 SUCCESS: Push "聊天记录_tbNick_n9c42_2026-05-17.md" completed! ....
对隐私/敏感信息的屏蔽保护 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 SELECT ID, post_title, post_date FROM wp_posts WHERE post_content LIKE '%13261977480%' ;UPDATE wp_posts SET post_content = REPLACE(post_content, '13261977480' , '1326****480' )WHERE post_content LIKE '%13261977480%' ;UPDATE wp_posts SET post_content = REPLACE(post_content, '后北营家园一区10号楼3-130' , '后北营家园一区10号(大运河果蔬便民店外)' )WHERE post_content LIKE '%后北营家园一区10号楼3-130%' ;UPDATE wp_posts SET post_content = REPLACE(post_content, 'VPN' , 'V*P*N' )WHERE post_content LIKE '%VPN%' ;UPDATE wp_posts SET post_title = REPLACE(post_title, '_2026-05-17' , '_手柄一修哥' )WHERE post_title LIKE '%_2026-05-17%' ;
维护商品分类 1 2 3 4 5 6 7 8 INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id, term_order)SELECT ID, 17 , 0 FROM wp_posts WHERE post_type = 'product' AND post_title like '%PS5%' and ID not in (select object_id from wp_term_relationships)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id, term_order)SELECT ID, 27 , 0 FROM wp_posts WHERE post_type = 'product' AND post_title like '%switch%' INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id, term_order)SELECT ID, 27 , 0 FROM wp_posts WHERE post_type = 'product' AND post_title like '%joycon%' #totally 43 row , success 23 , duplicated Updated rows 23 ; Duplicate entry '242-27' for key 'PRIMARY' Duplicate entry '432-27' for key 'PRIMARY' Duplicate entry '443-27' for key 'PRIMARY' Duplicate entry '455-27' for key 'PRIMARY' Duplicate entry '487-27' for key 'PRIMARY' Duplicate entry '506-27' for key 'PRIMARY' Duplicate entry '259-27' for key 'PRIMARY' Duplicate entry '293-27' for key 'PRIMARY' Duplicate entry '323-27' for key 'PRIMARY' Duplicate entry '578-27' for key 'PRIMARY' Duplicate entry '580-27' for key 'PRIMARY' Duplicate entry '606-27' for key 'PRIMARY' Duplicate entry '608-27' for key 'PRIMARY' Duplicate entry '615-27' for key 'PRIMARY' Duplicate entry '631-27' for key 'PRIMARY' Duplicate entry '652-27' for key 'PRIMARY' Duplicate entry '659-27' for key 'PRIMARY' Duplicate entry '682-27' for key 'PRIMARY' Duplicate entry '684-27' for key 'PRIMARY' Duplicate entry '695-27' for key 'PRIMARY'
17 ps5 93 27 Switch 133 joycon; duplicate lite, oled, 大气层
28 Xbox 35 29 SteamDeck 27 30 Quest3 6 31 PS4 6 32 IT支持 10 远程 10 ; 上门 4
33 NetSuite 1 34 掌机 3
未分类: 24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SELECT ID, 27 , 0 FROM wp_posts WHERE post_type = 'product' and wp_posts.ID not in (select object_id from wp_term_relationships) #更新分类的统计表 UPDATE wp_term_taxonomy SET count = ( SELECT COUNT (* ) FROM wp_term_relationships WHERE wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id ) WHERE term_taxonomy_id = 34
Next 搭建: 网站客服系统 docker 比如: https://zhuanlan.zhihu.com/p/23677870488
用于新增一个潜在客户直接语言沟通的机会, 直接在网站中聊天
快速上线的,但是无拓展功能(只能去付费拓展的)
https://www.tawk.to/software/live-chat/
https://www.twt.com/en/chat/pricing
https://github.com/chaskiq/chaskiq
https://github.com/chatwoot/chatwoot
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 version: '3.8' services: chaskiq-redis: image: redis:7-alpine container_name: chaskiq-redis restart: always chaskiq-app: image: chaskiq/chaskiq:latest container_name: chaskiq-app restart: always ports: - "3000:3000" environment: - HOST=http://localhost:3000 - SECRET_KEY_BASE=Another_very_long_random_string_64_chars - REDIS_URL=redis://chaskiq-redis:6379/1 DATABASE_URL=postgresql://umami:[email protected] :5434/chaskiq_prod
方案一:正确配置 Chatwoot Community 纯开源版(解除限制)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 version: '3.8' services: cskefu-redis: image: redis:7-alpine container_name: cskefu-redis restart: always chatwoot-web: image: chatwoot/chatwoot:latest container_name: chatwoot-web restart: always ports: - "3000:3000" environment: - FRONTEND_URL=http://localhost:3000 - SECRET_KEY_BASE=a_very_long_random_string_here_32_chars - ENABLE_ACCOUNT_LIMITS=false - INSTALLATION_ENV=docker - POSTGRES_HOST=172.17.0.1 - POSTGRES_PORT=5432 - POSTGRES_DATABASE=chatwoot_prod - POSTGRES_USERNAME=postgres - POSTGRES_PASSWORD=your_existing_postgres_password - REDIS_URL=redis://cskefu-redis:6379/0 command: bundle exec rails s -p 3000 -b '0.0.0.0' depends_on: - cskefu-redis chatwoot-worker: image: chatwoot/chatwoot:latest container_name: chatwoot-worker restart: always environment: - ENABLE_ACCOUNT_LIMITS=false - INSTALLATION_ENV=docker - POSTGRES_HOST=172.17.0.1 - POSTGRES_PORT=5432 - POSTGRES_DATABASE=chatwoot_prod - POSTGRES_USERNAME=postgres - POSTGRES_PASSWORD=your_existing_postgres_password - REDIS_URL=redis://cskefu-redis:6379/0 command: bundle exec sidekiq -g chatwoot -C config/sidekiq.yml depends_on: - cskefu-redis
SEO优化, 尝试提交Google 下载 wordpress sitemap generator 用于生成网站地图
下载zip, 上传安装后, 自动生成了http://w.carlzeng.com/sitemap.xml
状态: Processing data, please check again in a day or so
待下周重新查阅一下Google收录情况
https://ziyuan.baidu.com/linksubmit/url
Bing
提交了网站地图 http://w.carlzeng.com/sitemap.xml
Google Page Indexing issue
这个很简单, 按链接提示, 把货品图片补上即可.
Missing field “hasMerchantReturnPolicy” (in “offers”)
This is a non-critical issue. Items with these issues are valid, but could be presented with more features or be optimized for more relevant queries
这个已经在商品的详细页面添加了退款和退货策略 还是无法通过校验. 请高人指点.
總結:WPSSO Merchant Return Policy Manager 外掛可以幫助你輕鬆管理Google Merchant 列表的任何數量的退貨政策,同時修復遺失”hasMerchantReturnPolicy “ 的警告。
页面加载速度优化 去除首页的woocommerce区块, 避免照片的3M载入
下面这段是最能减负的, 让css减轻了首页和非commerce页面的负担
1 2 3 4 5 6 7 8 9 10 11 12 13 /** * 禁用 WooCommerce 所有的 CSS 样式和 JS 脚本 */ add_action( 'template_redirect', 'remove_woocommerce_styles_scripts', 999 ); function remove_woocommerce_styles_scripts() { if ( function_exists( 'is_woocommerce' ) ) { if ( ! is_woocommerce() && ! is_cart() && ! is_checkout() ) { remove_action('wp_enqueue_scripts', [WC_Frontend_Scripts::class, 'load_scripts']); remove_action('wp_print_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5); remove_action('wp_print_footer_scripts', [WC_Frontend_Scripts::class, 'localize_printed_scripts'], 5); } } }
解决问题: wordpress首页并没有放woocommerce组件 页面很多woocommerce的css
速度检测网站: https://tools.pingdom.com
用CDN把JS给缓存起来, 能有效的提升网站访问速度
优化n.carlzeng.com访问速度
20260620 优化了所有照片, 剪裁尺寸到500px - 1000px (宽度最大值)
但是cloudflare缓存了之前大照片的, 大文件;
TODO: 等待cloudflare刷新缓存, 看需要耗时多久?
半小时左右还是有问题的:
0621第二天了, 用tools.pingdom.com来查询整个网址 还有1.8MB; 照片还有257kb的, 说明CDN的缓存还在生效, 怎么刷新cloudflare的cdn?
操作步骤
登录 dash.cloudflare.com ,选中你的域名
左侧菜单:Caching(缓存) → Configuration(配置)
找到 Purge Cache 区域,点击 Custom Purge(自定义清除)
可以purge特定的URL资源, 或者整个站点清除, 或者 全部清除.
开启「开发模式 Development Mode」临时禁用缓存
域名首页 Overview 页面
找到 Development Mode 开关打开(持续 3 小时)
此时所有资源直接回源,不会走 CDN 缓存,用来验证源站图片是否真的替换成功
1:15pm 已经提交过了好几分钟, 重新用浏览器还是看到了旧的图片大小内容; Monitor 要多久才能更新缓存?
0622 又是一个; purge后第二天, clashflare扯淡的, 不会刷新不回purge(用域名的方式已尝试) 重新尝试使用 URL prefix的方式 purge n.carlzeng.com/wp-content; 再一次拭目以待
9am URL访问源站点, 肯定已经清除到最新的小图片了; 开了develpment mode 持续3小时
0623 等了一天, 依旧无法刷新缓存. 验证方法
1 2 curl -I https://n.carlzeng.com/wp-content/uploads/20 26/06/image-3.png
域名 Overview 页面点击「Pause Cloudflare on Site」,完全停用 CDN 测试图片
pause后马上测试, 依旧是无法生效的, 依旧是 HIT cf-cache-status
分享媒体库中的照片 chmod 644 media-images.php
1 /volume2/KingchuxingSSD512G/docker/compose/wordpress2/wordpresshtml# vi getimages.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 <?php $dir = __DIR__ ;for ($i = 0 ; $i < 5 ; $i ++) { if (file_exists ($dir . '/wp-load.php' )) { require_once ($dir . '/wp-load.php' ); break ; } $dir = dirname ($dir ); } $images = get_posts ([ 'post_type' => 'attachment' , 'post_mime_type' => 'image' , 'post_status' => 'inherit' , 'posts_per_page' => -1 , ]); ?> <!DOCTYPE html> <html lang="zh-CN" > <head> <meta charset="UTF-8" > <title>案例图片 - 手柄一修哥</title> <meta name="viewport" content="width=device-width, initial-scale=1" > <!-- Cloudflare CDN: baguetteBox CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.11.1/baguetteBox.min.css" > <style> *{margin:0 ;padding:0 ;box-sizing:border-box} body{background: .grid{display:grid;grid-template-columns:repeat (auto-fill,minmax (180 px,1 fr));gap:15 px;margin-top:20 px} .card{background: img{width:100 %;height:140 px;object -fit:cover;display:block;background: img.lazy{opacity:0 ;transition:opacity 0.3 s} img.lazy.loaded{opacity:1 } h3 a { text-decoration: none !important; } </style> </head> <body> <h3>✅ <a href="https://w.carlzeng.com" target='_blank' >案例图库:<?php echo count ($images ); ?> 张(手柄一修哥工作室w.carlzeng.com)</a></h3> <div class ="grid " id ="gallery "> <?php foreach ($images as $img ): $img_url = wp_get_attachment_image_url ($img ->ID , 'medium '); $full_url = wp_get_attachment_image_url ($img ->ID , 'full '); ?> <div class ="card "> <a href ="<?php echo $full_url ; ?>" class ="gallery -item "> <img class ="lazy " data -src ="<?php echo $img_url ; ?>" alt =""> </a > </div > <?php endforeach ; ?> </div > <script src ="https ://cdnjs .cloudflare .com /ajax /libs /vanilla -lazyload /17.1.0/lazyload .min .js "></script > <script src ="https ://cdnjs .cloudflare .com /ajax /libs /baguettebox .js /1.11.1/baguetteBox .min .js "></script > <script > // 懒加载初始化 new LazyLoad ( { elements_selector: ".lazy" }); baguetteBox.run ('#gallery' , { animation : 'fadeIn' , noScrollbars : true }); </script> <!-- Matomo --> <script> var _paq = window._paq = window._paq || []; _paq.push (["setDocumentTitle" , document.domain + "/" + document.title]); _paq.push (["setCookieDomain" , "*.carlzeng.com" ]); _paq.push (['trackPageView' ]); _paq.push (['enableLinkTracking' ]); (function ( ) { var u="//statcounter.carlzeng.com/" ; _paq.push (['setTrackerUrl' , u+'matomo.php' ]); _paq.push (['setSiteId' , '1' ]); var d=document, g=d.createElement ('script' ), s=d.getElementsByTagName ('script' )[0 ]; g.async=true ; g.src=u+'matomo.js' ; s.parentNode.insertBefore (g,s); })(); </script> <noscript><p><img src="//statcounter.carlzeng.com/matomo.php?idsite=1&rec=1" style="border:0;" alt="" /></p></noscript> <!-- End Matomo Code --> <script defer="" src="https://umami.carlzeng.com:3/script.js" data-website-id="84261200-b106-4d11-8bc3-ad3b395a3f31" ></script> </body> </html>
修正文章中的URL地址 由于切换使用CDN等缘故, 修改源文章中的链接
Mariadb中更新
1 2 3 4 5 select * from wp_posts where post_content LIKE '%https://query.carlzeng.com:3/%' UPDATE wp_posts SET post_content= REPLACE(post_content,'https://query.carlzeng.com:3/' ,'https://query.carlzeng.com/' )
下载sqllite的数据库, 同样在数据库中更新
灵感来源与项目计划 WordPress 告别 MySQL:Docker SQLite WordPress
我写了个从 Obsidian 自动发布文章到微信公众号的工具
个性化需求沟通 扫客服加V加群: