diff --git a/docs/travel.md b/docs/travel.md
index 70021e3dac..786574a985 100644
--- a/docs/travel.md
+++ b/docs/travel.md
@@ -57,6 +57,14 @@ IATA 国际航空运输协会机场代码, 参见[维基百科 国际航空运
+### 信用卡
+
+
+
+| 国内信用卡 | 浦发银行 | 招商银行 | 中信银行 | 交通银行 | 中国银行 | 工商银行 | 广发银行 | 农业银行 | 建设银行 | 汇丰银行 | 民生银行 | 兴业银行 | 花旗银行 | 无卡支付 | 投资理财 | 网站权益汇 | 境外信用卡 |
+| ---------- | -------- | --------- | -------- | -------- | --------- | --------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | ---------- | ------------- |
+| creditcard | pufa | zhaoshang | zhongxin | jiaotong | zhonghang | gongshang | guangfa | nongye | jianshe | huifeng | mingsheng | xingye | huaqi | wuka | 137 | 145 | intcreditcard |
+
## 国家地理
### 分类
diff --git a/lib/router.js b/lib/router.js
index 71ea55c34d..5d1fd9ff10 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1443,6 +1443,7 @@ router.get('/aiyanxishe/:id/:sort?', require('./routes/aiyanxishe/home'));
// 飞客茶馆优惠信息
router.get('/flyertea/preferential', require('./routes/flyertea/preferential'));
+router.get('/flyertea/creditcard/:bank', require('./routes/flyertea/creditcard'));
// 中国广播
router.get('/radio/:channelname/:name', require('./routes/radio/radio'));
diff --git a/lib/routes/flyertea/creditcard.js b/lib/routes/flyertea/creditcard.js
new file mode 100644
index 0000000000..8ebce4a8a1
--- /dev/null
+++ b/lib/routes/flyertea/creditcard.js
@@ -0,0 +1,85 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const util = require('./utils');
+const iconv = require('iconv-lite');
+
+const gbk2utf8 = (s) => iconv.decode(s, 'gbk');
+const host = 'https://www.flyertea.com';
+
+module.exports = async (ctx) => {
+ const bank = ctx.params.bank;
+ const target = `${host}/forum-${bank}-1.html`;
+ let bankname = '';
+
+ switch (bank) {
+ case 'creditcard':
+ bankname = '国内信用卡';
+ break;
+ case 'pufa':
+ bankname = '浦发银行';
+ break;
+ case 'zhaoshang':
+ bankname = '招商银行';
+ break;
+ case 'zhongxin':
+ bankname = '中信银行';
+ break;
+ case 'jiaotong':
+ bankname = '交通银行';
+ break;
+ case 'zhonghang':
+ bankname = '中国银行';
+ break;
+ case 'gongshang':
+ bankname = '工商银行';
+ break;
+ case 'guangfa':
+ bankname = '广发银行';
+ break;
+ case 'nongye':
+ bankname = '农业银行';
+ break;
+ case 'jianshe':
+ bankname = '建设银行';
+ break;
+ case 'huifeng':
+ bankname = '汇丰银行';
+ break;
+ case 'mingsheng':
+ bankname = '民生银行';
+ break;
+ case 'xingye':
+ bankname = '兴业银行';
+ break;
+ case 'huaqi':
+ bankname = '花旗银行';
+ break;
+ case 'wuka':
+ bankname = '无卡支付';
+ break;
+ case '137':
+ bankname = '投资理财';
+ break;
+ case '145':
+ bankname = '网站权益汇';
+ break;
+ case 'intcreditcard':
+ bankname = '境外信用卡';
+ }
+
+ const response = await got.get(target, {
+ responseType: 'buffer',
+ });
+
+ const $ = cheerio.load(gbk2utf8(response.data));
+ const list = $("[id*='normalthread']").get();
+
+ const result = await util.ProcessFeed(list, ctx.cache);
+
+ ctx.state.data = {
+ title: `飞客茶馆信用卡 - ${bankname}`,
+ link: 'https://www.flyertea.com/',
+ description: `飞客茶馆信用卡 - ${bankname}`,
+ item: result,
+ };
+};
diff --git a/lib/routes/flyertea/utils.js b/lib/routes/flyertea/utils.js
new file mode 100644
index 0000000000..8a0bfe5c85
--- /dev/null
+++ b/lib/routes/flyertea/utils.js
@@ -0,0 +1,66 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const url = require('url');
+const iconv = require('iconv-lite');
+
+// 加载文章页
+async function load(link) {
+ const response = await got.get(link, {
+ responseType: 'buffer',
+ });
+ const gbk2utf8 = (s) => iconv.decode(s, 'gbk');
+ const $ = cheerio.load(gbk2utf8(response.data));
+
+ // 去除全文末尾多与内容
+ $('.lookMore').remove();
+ $('script').remove();
+
+ // 修改图片中的链接
+ $('ignore_js_op img').each(function() {
+ const new_src = $('ignore_js_op img').attr('file');
+ $(this).attr('src', new_src);
+ });
+
+ // 去除全文中图片的多余标签
+ const images = $('ignore_js_op img');
+ $('ignore_js_op').remove();
+ $("[class*='post_message']").append(images);
+
+ // 提取内容
+ const description = $("[class*='post_message']").html();
+
+ return { description };
+}
+
+const ProcessFeed = async (list, caches) => {
+ const host = 'https://www.flyertea.com';
+
+ return await Promise.all(
+ list.map(async (item) => {
+ const $ = cheerio.load(item);
+
+ const $label = $(".comiis_common a[data-track='版块页主题分类']");
+ const $title = $(".comiis_common a[data-track='版块页帖子']");
+ // 还原相对链接为绝对链接
+ const itemUrl = url.resolve(host, $title.attr('href'));
+
+ // 列表上提取到的信息
+ const single = {
+ title: $label.text() + '-' + $title.text(),
+ link: itemUrl,
+ guid: itemUrl,
+ };
+
+ // 使用tryGet方法从缓存获取内容。
+ // 当缓存中无法获取到链接内容的时候,则使用load方法加载文章内容。
+ const other = await caches.tryGet(itemUrl, async () => await load(itemUrl));
+
+ // 合并解析后的结果集作为该篇文章最终的输出结果
+ return Promise.resolve(Object.assign({}, single, other));
+ })
+ );
+};
+
+module.exports = {
+ ProcessFeed,
+};