diff --git a/assets/radar-rules.js b/assets/radar-rules.js
index 4e8a6ca9d4..71386b2606 100644
--- a/assets/radar-rules.js
+++ b/assets/radar-rules.js
@@ -2447,6 +2447,15 @@
},
],
},
+ 'craigslist.org': {
+ _name: 'Craigslist',
+ '.': [
+ {
+ title: '商品搜索列表',
+ docs: 'https://docs.rsshub.app/shopping.html#craigslist',
+ },
+ ],
+ },
'saraba1st.com': {
_name: 'Saraba1st',
bbs: [
diff --git a/docs/shopping.md b/docs/shopping.md
index 245fb3049d..eae0a16575 100644
--- a/docs/shopping.md
+++ b/docs/shopping.md
@@ -36,6 +36,19 @@ pageClass: routes
+## Craigslist
+
+### 商品搜索
+
+
+
+> 由于 Craigslist 取消了 RSS 订阅搜索功能,因此用 RSSHub 来实现了类似效果。
+> 一个完整原始搜索会像这样:
+>
+>
+> /search/xxx 后跟的 "xxx" 为搜索类型,直接参考原始请求即可。
+> query string 是实际的搜索内容。
+
## Furstar
### 最新售卖角色列表
diff --git a/lib/router.js b/lib/router.js
index f3bfeb4c87..7926d84115 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -3704,4 +3704,7 @@ router.get('/asml/press-releases', require('./routes/asml/press-releases'));
// 中国机械工程学会
router.get('/cmes/news/:category?', require('./routes/cmes/news'));
+// Craigslist
+router.get('/craigslist/:location/:type', require('./routes/craigslist/search'));
+
module.exports = router;
diff --git a/lib/routes/craigslist/search.js b/lib/routes/craigslist/search.js
new file mode 100644
index 0000000000..691f79f040
--- /dev/null
+++ b/lib/routes/craigslist/search.js
@@ -0,0 +1,46 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const queryParams = ctx.request.querystring;
+ const queryUrl = `https://${ctx.params.location}.craigslist.org/search/${ctx.params.type}?${queryParams}`;
+ const { data } = await got.get(queryUrl);
+ const $ = cheerio.load(data);
+ const items = $('.result-row')
+ .slice(0, 20)
+ .map((_, _item) => {
+ const item = $(_item);
+ const info = item.find('.result-info').first();
+ const titleNode = info.find('.result-title').first();
+ const price = info.find('.result-price').first().text();
+ const hood = info.find('.result-hood').first().text();
+ const date = info.find('time').first().attr('datetime');
+
+ const dataIds = item.find('.result-image').first().attr('data-ids');
+ let desc = '';
+ if (dataIds) {
+ const imageList = dataIds.split(',').map((id) => `
`);
+ desc = imageList.join('');
+ }
+ return {
+ title: price + ' - ' + titleNode.text() + hood,
+ link: titleNode.attr('href'),
+ description: desc,
+ pubDate: date,
+ guid: titleNode.attr('id'),
+ };
+ })
+ .get();
+ const urlParams = new URLSearchParams(queryParams);
+ let itemName = urlParams.get('query');
+ if (!itemName) {
+ itemName = '';
+ } else {
+ itemName = itemName.replace('+', ' ');
+ }
+ ctx.state.data = {
+ title: itemName + ' - Craigslist',
+ link: queryUrl,
+ item: items,
+ };
+};