diff --git a/docs/en/README.md b/docs/en/README.md
index 5772c2f65..9d534b178 100644
--- a/docs/en/README.md
+++ b/docs/en/README.md
@@ -664,6 +664,12 @@ Supported sub-sites:
+### Japanpost
+
+#### Track & Trace Service
+
+
+
## aptonic
### New Dropzone Actions
diff --git a/docs/joinus/README.md b/docs/joinus/README.md
index 605b5dcc4..09f5d11a1 100644
--- a/docs/joinus/README.md
+++ b/docs/joinus/README.md
@@ -416,7 +416,7 @@ ctx.state.data = {
### 步骤 3: 添加脚本文档
-1. 更新 [文档 (/docs/README.md) ](https://github.com/DIYgod/RSSHub/blob/master/docs/README.md), 可以执行 `npm run docs:dev` 查看文档效果
+1. 更新 [文档 (/docs/) ](https://github.com/DIYgod/RSSHub/blob/master/docs/) 目录内对应的文档, 可以执行 `npm run docs:dev` 查看文档效果
- 文档采用 vue 组件形式,格式如下:
- `author`: 路由作者,多位作者使用单个空格分隔
diff --git a/docs/other.md b/docs/other.md
index 6e83bd8b0..645ec5ad2 100644
--- a/docs/other.md
+++ b/docs/other.md
@@ -849,6 +849,12 @@ type 为 all 时,category 参数不支持 cost 和 free
+## 日本郵便
+
+### 郵便追跡サービス
+
+
+
## 扇贝
### 打卡
diff --git a/lib/router.js b/lib/router.js
index 45015a223..7925d5c65 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1581,6 +1581,9 @@ router.get('/leboncoin/ad/:query', require('./routes/leboncoin/ad.js'));
// DHL
router.get('/dhl/:id', require('./routes/dhl/shipment-tracking'));
+// Japanpost
+router.get('/japanpost/:reqCode', require('./routes/japanpost/index'));
+
// 中华人民共和国商务部
router.get('/mofcom/article/:suffix', require('./routes/mofcom/article'));
diff --git a/lib/routes/japanpost/index.js b/lib/routes/japanpost/index.js
new file mode 100644
index 000000000..78070b6e1
--- /dev/null
+++ b/lib/routes/japanpost/index.js
@@ -0,0 +1,60 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const utils = require('./utils');
+
+const baseTitle = '日本郵便';
+const baseUrl = 'https://trackings.post.japanpost.jp/services/srv/search/direct?locale=ja&reqCodeNo1=';
+
+const util = new utils();
+util.expandEven();
+util.expandReverse();
+
+module.exports = async (ctx) => {
+ const reqCode = ctx.params.reqCode;
+ const link = baseUrl + reqCode;
+
+ const response = await got({
+ method: 'get',
+ url: link,
+ });
+
+ const $ = cheerio.load(response.data);
+ const list = $('.tableType01')
+ .eq(1)
+ .find('tr')
+ .slice(2);
+
+ const listEven = list.even();
+
+ const packageType = $('.tableType01')
+ .eq(0)
+ .find('tr')
+ .eq(1)
+ .find('td')
+ .eq(1)
+ .text();
+
+ ctx.state.data = {
+ title: `${baseTitle} ${packageType} ${reqCode}`,
+ link: link,
+ description: 'Reserved for further development.',
+ item: listEven
+ .reverse()
+ .map((index, item) => {
+ item = $(item);
+ const itemTd = item.find('td');
+ const itemTitle = itemTd.eq(1).text() + ' ' + itemTd.eq(4).text() + ' ' + itemTd.eq(3).text();
+ const itemDescription = itemTd.eq(2).text();
+ const itemPubDateText = itemTd.eq(0).text();
+ const itemGuid = util.generateGuid(itemDescription + itemPubDateText);
+ return {
+ title: itemTitle,
+ description: itemDescription,
+ pubDate: new Date(itemPubDateText),
+ link: link,
+ guid: itemGuid.slice(0, 32),
+ };
+ })
+ .get(),
+ };
+};
diff --git a/lib/routes/japanpost/utils.js b/lib/routes/japanpost/utils.js
new file mode 100644
index 000000000..88d33353f
--- /dev/null
+++ b/lib/routes/japanpost/utils.js
@@ -0,0 +1,48 @@
+const cheerio = require('cheerio');
+const crypto = require('crypto');
+
+function utils() {
+ this.expandOdd = function() {
+ cheerio.prototype.odd = function() {
+ const odds = [];
+ this.each(function(index, item) {
+ if (index % 2 === 1) {
+ odds.push(item);
+ }
+ });
+ return cheerio(odds);
+ };
+ };
+
+ this.expandEven = function() {
+ cheerio.prototype.even = function() {
+ const evens = [];
+ this.each(function(index, item) {
+ if (index % 2 === 0) {
+ evens.push(item);
+ }
+ });
+ return cheerio(evens);
+ };
+ };
+
+ this.expandReverse = function() {
+ cheerio.prototype.reverse = function() {
+ const reverses = [];
+ this.each(function(index, item) {
+ reverses.push(item);
+ });
+ reverses.reverse();
+ return cheerio(reverses);
+ };
+ };
+
+ this.generateGuid = function(t) {
+ const hash = crypto.createHash('sha512');
+ hash.update(t);
+ const r = hash.digest('hex').toUpperCase();
+ return r;
+ };
+}
+
+module.exports = utils;