diff --git a/lib/router.js b/lib/router.js
index 5958b06b04..9ba588b478 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -376,7 +376,7 @@ router.get('/autotrader/:query', lazyloadRouteHandler('./routes/autotrader'));
router.get('/geekpark/breakingnews', lazyloadRouteHandler('./routes/geekpark/breakingnews'));
// 搜狗
-router.get('/sogou/doodles', lazyloadRouteHandler('./routes/sogou/doodles'));
+// router.get('/sogou/doodles', lazyloadRouteHandler('./routes/sogou/doodles'));
// 香港天文台
router.get('/hko/weather', lazyloadRouteHandler('./routes/hko/weather'));
@@ -690,7 +690,7 @@ router.get('/digitaling/articles/:category/:subcate?', lazyloadRouteHandler('./r
router.get('/digitaling/projects/:category', lazyloadRouteHandler('./routes/digitaling/project'));
// Bing壁纸
-router.get('/bing', lazyloadRouteHandler('./routes/bing/index'));
+// router.get('/bing', lazyloadRouteHandler('./routes/bing/index'));
// AlgoCasts
router.get('/algocasts', lazyloadRouteHandler('./routes/algocasts/all'));
diff --git a/lib/v2/baidu/maintainer.js b/lib/v2/baidu/maintainer.js
index 7cbf506d11..b196204cb6 100644
--- a/lib/v2/baidu/maintainer.js
+++ b/lib/v2/baidu/maintainer.js
@@ -1,5 +1,6 @@
module.exports = {
'/gushitong/index': ['CaoMeiYouRen'],
+ '/search/:keyword': ['CaoMeiYouRen'],
'/tieba/forum/good/:kw/:cid?/:sortBy?': ['u3u'],
'/tieba/forum/:kw/:sortBy?': ['u3u'],
'/tieba/post/:id': ['u3u'],
diff --git a/lib/v2/baidu/radar.js b/lib/v2/baidu/radar.js
index 20b2b9e809..5d91512855 100644
--- a/lib/v2/baidu/radar.js
+++ b/lib/v2/baidu/radar.js
@@ -1,6 +1,17 @@
module.exports = {
'baidu.com': {
_name: '百度',
+ www: [
+ {
+ title: '搜索',
+ docs: 'https://docs.rsshub.app/routes/other#bai-du-sou-suo',
+ source: ['/'],
+ target: (params, url) => {
+ const keyword = new URL(url).searchParams.get('wd');
+ return `/baidu/search/${keyword}`;
+ },
+ },
+ ],
gushitong: [
{
title: '首页指数',
@@ -73,7 +84,7 @@ module.exports = {
top: [
{
title: '热搜榜单',
- docs: 'https://docs.rsshub.app/routes/other#bai-du-re-sou',
+ docs: 'https://docs.rsshub.app/routes/other#bai-du-re-sou-bang-dan',
source: ['/board'],
target: (_, url) => `/baidu/top/${new URL(url).searchParams.get('tab')}`,
},
diff --git a/lib/v2/baidu/router.js b/lib/v2/baidu/router.js
index e838568aab..3ccdbd2025 100644
--- a/lib/v2/baidu/router.js
+++ b/lib/v2/baidu/router.js
@@ -1,5 +1,6 @@
module.exports = (router) => {
router.get('/gushitong/index', require('./gushitong'));
+ router.get('/search/:keyword', require('./search'));
router.get('/tieba/forum/good/:kw/:cid?/:sortBy?', require('./tieba/forum'));
router.get('/tieba/forum/:kw/:sortBy?', require('./tieba/forum'));
router.get('/tieba/post/:id', require('./tieba/post'));
diff --git a/lib/v2/baidu/search.js b/lib/v2/baidu/search.js
new file mode 100644
index 0000000000..6c8def76a5
--- /dev/null
+++ b/lib/v2/baidu/search.js
@@ -0,0 +1,54 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { art } = require('@/utils/render');
+const path = require('path');
+const renderDescription = (description, images) => art(path.join(__dirname, './templates/description.art'), { description, images });
+const config = require('@/config').value;
+
+module.exports = async (ctx) => {
+ const { keyword } = ctx.params;
+ const url = `https://www.baidu.com/s?wd=${encodeURIComponent(keyword)}`;
+ const key = `baidu-search:${url}`;
+
+ const items = await ctx.cache.tryGet(
+ key,
+ async () => {
+ const response = (await got(url)).data;
+ const visitedLinks = new Set();
+ const $ = cheerio.load(response);
+ const contentLeft = $('#content_left');
+ const containers = contentLeft.find('.c-container');
+ return containers
+ .map((i, el) => {
+ const element = $(el);
+ const link = element.find('h3 a').first().attr('href');
+ if (link && !visitedLinks.has(link)) {
+ visitedLinks.add(link);
+ const imgs = element
+ .find('img')
+ .map((_j, _el) => $(_el).attr('src'))
+ .toArray();
+ const description = element.find('.c-gap-top-small [class^="content-right_"]').first().text() || element.find('.c-row').first().text() || element.find('.cos-row').first().text();
+ return {
+ title: element.find('h3').first().text(),
+ description: renderDescription(description, imgs),
+ link: element.find('h3 a').first().attr('href'),
+ author: element.find('.c-row .c-color-gray').first().text() || '',
+ };
+ }
+ return null;
+ })
+ .toArray()
+ .filter((e) => e?.link);
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ ctx.state.data = {
+ title: `${keyword} - 百度搜索`,
+ description: `${keyword} - 百度搜索`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/baidu/templates/description.art b/lib/v2/baidu/templates/description.art
new file mode 100644
index 0000000000..5f98f4ca33
--- /dev/null
+++ b/lib/v2/baidu/templates/description.art
@@ -0,0 +1,6 @@
+{{@ description }}
+{{if images}}
+ {{each images}}
+
+ {{/each}}
+{{/if}}
diff --git a/lib/routes/bing/index.js b/lib/v2/bing/daily-wallpaper.js
similarity index 78%
rename from lib/routes/bing/index.js
rename to lib/v2/bing/daily-wallpaper.js
index cf69bda81c..2eaf345ff3 100644
--- a/lib/routes/bing/index.js
+++ b/lib/v2/bing/daily-wallpaper.js
@@ -1,22 +1,21 @@
const got = require('@/utils/got');
-const queryString = require('query-string');
module.exports = async (ctx) => {
const response = await got({
method: 'get',
prefixUrl: 'https://cn.bing.com',
url: 'HPImageArchive.aspx',
- searchParams: queryString.stringify({
+ searchParams: {
format: 'js',
idx: 0,
- n: 7,
+ n: ctx.query.limit ? parseInt(ctx.query.limit, 10) : 7,
mkt: 'zh-CN',
- }),
+ },
});
const data = response.data;
ctx.state.data = {
title: 'Bing每日壁纸',
- link: `https://cn.bing.com/`,
+ link: 'https://cn.bing.com/',
item: data.images.map((item) => ({
title: item.copyright,
description: `
`,
diff --git a/lib/v2/bing/maintainer.js b/lib/v2/bing/maintainer.js
new file mode 100644
index 0000000000..e20ecae190
--- /dev/null
+++ b/lib/v2/bing/maintainer.js
@@ -0,0 +1,4 @@
+module.exports = {
+ '/': ['FHYunCai'],
+ '/search/:keyword': ['CaoMeiYouRen'],
+};
diff --git a/lib/v2/bing/radar.js b/lib/v2/bing/radar.js
new file mode 100644
index 0000000000..9023c3cf4b
--- /dev/null
+++ b/lib/v2/bing/radar.js
@@ -0,0 +1,22 @@
+module.exports = {
+ 'bing.com': {
+ _name: 'Bing',
+ cn: [
+ {
+ title: '每日壁纸',
+ docs: 'https://docs.rsshub.app/routes/picture#bing',
+ source: '/',
+ target: '/bing',
+ },
+ {
+ title: '搜索',
+ docs: 'https://docs.rsshub.app/routes/other#bing',
+ source: '/',
+ target: (params, url) => {
+ const q = new URL(url).searchParams.get('q');
+ return `/bing/search/${q}`;
+ },
+ },
+ ],
+ },
+};
diff --git a/lib/v2/bing/router.js b/lib/v2/bing/router.js
new file mode 100644
index 0000000000..da2dfe81c1
--- /dev/null
+++ b/lib/v2/bing/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/', require('./daily-wallpaper'));
+ router.get('/search/:keyword', require('./search'));
+};
diff --git a/lib/v2/bing/search.js b/lib/v2/bing/search.js
new file mode 100644
index 0000000000..41c021da78
--- /dev/null
+++ b/lib/v2/bing/search.js
@@ -0,0 +1,28 @@
+const parser = require('@/utils/rss-parser');
+const { parseDate } = require('@/utils/parse-date');
+const dayjs = require('dayjs');
+const localizedFormat = require('dayjs/plugin/localizedFormat');
+require('dayjs/locale/zh-cn');
+dayjs.extend(localizedFormat);
+
+module.exports = async (ctx) => {
+ const q = ctx.params.keyword;
+ const searchParams = new URLSearchParams({
+ format: 'rss',
+ q,
+ });
+ const url = new URL('https://cn.bing.com/search');
+ url.search = searchParams.toString();
+ const data = await parser.parseURL(url.toString());
+ ctx.state.data = {
+ title: data.title,
+ link: data.link,
+ description: data.description + ' - ' + data.copyright,
+ image: data.image.url,
+ item: data.items.map((e) => ({
+ ...e,
+ description: e.content,
+ pubDate: parseDate(e.pubDate, 'dddd, DD MMM YYYY HH:mm:ss [GMT]', 'zh-cn'),
+ })),
+ };
+};
diff --git a/lib/v2/google/maintainer.js b/lib/v2/google/maintainer.js
index cbdd6ddd34..6abbdd362c 100644
--- a/lib/v2/google/maintainer.js
+++ b/lib/v2/google/maintainer.js
@@ -6,6 +6,7 @@ module.exports = {
'/fonts/:sort?': ['Fatpandac'],
'/news/:category/:locale': ['zoenglinghou'],
'/scholar/:query': ['HenryQW'],
+ '/search/:keyword/:language?': ['CaoMeiYouRen'],
'/sites/:id': ['hoilc'],
'/sites/recentChanges/:id': ['nczitzk'],
};
diff --git a/lib/v2/google/radar.js b/lib/v2/google/radar.js
index 11a15acbb6..998151b5ba 100644
--- a/lib/v2/google/radar.js
+++ b/lib/v2/google/radar.js
@@ -1,6 +1,18 @@
module.exports = {
'google.com': {
_name: '谷歌',
+ www: [
+ {
+ title: '搜索',
+ docs: 'https://docs.rsshub.app/routes/other#google',
+ source: '/',
+ target: (params, url, document) => {
+ const q = new URL(url).searchParams.get('q');
+ const lang = document.documentElement.lang;
+ return `/google/search/${q}/${lang}`;
+ },
+ },
+ ],
chrome: [
{
title: '插件更新',
diff --git a/lib/v2/google/router.js b/lib/v2/google/router.js
index b3064cf1cc..b4f2327971 100644
--- a/lib/v2/google/router.js
+++ b/lib/v2/google/router.js
@@ -6,4 +6,5 @@ module.exports = function (router) {
router.get('/fonts/:sort?', require('./fonts'));
router.get('/news/:category/:locale', require('./news'));
router.get('/scholar/:query', require('./scholar'));
+ router.get('/search/:keyword/:language?', require('./search'));
};
diff --git a/lib/v2/google/search.js b/lib/v2/google/search.js
new file mode 100644
index 0000000000..da45fb8868
--- /dev/null
+++ b/lib/v2/google/search.js
@@ -0,0 +1,62 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { art } = require('@/utils/render');
+const path = require('path');
+const config = require('@/config').value;
+
+const renderDescription = (description, images) => art(path.join(__dirname, './templates/description.art'), { description, images });
+
+module.exports = async (ctx) => {
+ const { keyword, language } = ctx.params;
+ const searchParams = new URLSearchParams({
+ q: keyword,
+ });
+ const tempUrl = new URL('https://www.google.com/search');
+ tempUrl.search = searchParams.toString();
+ const url = tempUrl.toString();
+ const key = `google-search:${language}:${url}`;
+ const items = await ctx.cache.tryGet(
+ key,
+ async () => {
+ const response = (
+ await got(url, {
+ headers: {
+ 'Accept-Language': language,
+ },
+ })
+ ).data;
+ const $ = cheerio.load(response);
+ const content = $('#rso');
+ return content
+ .find('> div')
+ .map((i, el) => {
+ const element = $(el);
+ const link = element.find('div > div > div > div > div > span > a').first().attr('href');
+ const title = element.find('div > div > div> div > div > span > a > h3').first().text();
+ const imgs = element
+ .find('img')
+ .map((_j, _el) => $(_el).attr('src'))
+ .toArray();
+ const description = element.find('div[style="-webkit-line-clamp:2"]').first().text() || element.find('div[role="heading"]').first().text();
+ const author = element.find('div > div > div > div > div > span > a > div > div > span').first().text() || '';
+ return {
+ link,
+ title,
+ description: renderDescription(description, imgs),
+ author,
+ };
+ })
+ .toArray()
+ .filter((e) => e?.link);
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ ctx.state.data = {
+ title: `${keyword} - Google Search`,
+ description: `${keyword} - Google Search`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/google/templates/description.art b/lib/v2/google/templates/description.art
new file mode 100644
index 0000000000..5f98f4ca33
--- /dev/null
+++ b/lib/v2/google/templates/description.art
@@ -0,0 +1,6 @@
+{{@ description }}
+{{if images}}
+ {{each images}}
+
+ {{/each}}
+{{/if}}
diff --git a/lib/routes/sogou/doodles.js b/lib/v2/sogou/doodles.js
similarity index 100%
rename from lib/routes/sogou/doodles.js
rename to lib/v2/sogou/doodles.js
diff --git a/lib/v2/sogou/maintainer.js b/lib/v2/sogou/maintainer.js
new file mode 100644
index 0000000000..b94d21c1b2
--- /dev/null
+++ b/lib/v2/sogou/maintainer.js
@@ -0,0 +1,4 @@
+module.exports = {
+ '/doodles': ['xyqfer'],
+ '/search/:keyword': ['CaoMeiYouRen'],
+};
diff --git a/lib/v2/sogou/radar.js b/lib/v2/sogou/radar.js
new file mode 100644
index 0000000000..a548c7fad7
--- /dev/null
+++ b/lib/v2/sogou/radar.js
@@ -0,0 +1,16 @@
+module.exports = {
+ 'sogou.com': {
+ _name: '搜狗',
+ www: [
+ {
+ title: '搜索',
+ docs: 'https://docs.rsshub.app/routes/other#sou-gou-sou-suo',
+ source: '/',
+ target: (params, url) => {
+ const keyword = new URL(url).searchParams.get('query');
+ return `/sogou/search/${keyword}`;
+ },
+ },
+ ],
+ },
+};
diff --git a/lib/v2/sogou/router.js b/lib/v2/sogou/router.js
new file mode 100644
index 0000000000..6dbfd72eb5
--- /dev/null
+++ b/lib/v2/sogou/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/doodles', require('./doodles'));
+ router.get('/search/:keyword', require('./search'));
+};
diff --git a/lib/v2/sogou/search.js b/lib/v2/sogou/search.js
new file mode 100644
index 0000000000..9cdb634548
--- /dev/null
+++ b/lib/v2/sogou/search.js
@@ -0,0 +1,54 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { art } = require('@/utils/render');
+const path = require('path');
+const { parseDate } = require('@/utils/parse-date');
+const config = require('@/config').value;
+
+const renderDescription = (description, images) => art(path.join(__dirname, './templates/description.art'), { description, images });
+
+module.exports = async (ctx) => {
+ const { keyword } = ctx.params;
+ const url = `https://www.sogou.com/web?query=${encodeURIComponent(keyword)}`;
+ const key = `sogou-search:${url}`;
+ const items = await ctx.cache.tryGet(
+ key,
+ async () => {
+ const response = (await got(url)).data;
+ const $ = cheerio.load(response);
+ const result = $('#main');
+ return result
+ .find('.vrwrap')
+ .map((i, el) => {
+ const element = $(el);
+ const imgs = element
+ .find('img')
+ .map((j, el2) => $(el2).attr('src'))
+ .toArray();
+ const link = element.find('h3 a').first().attr('href');
+ const title = element.find('h3').first().text();
+ const description = element.find('.text-layout').first().text() || element.find('.space-txt').first().text() || element.find('[class^="translate"]').first().text();
+ const author = element.find('.citeurl span').first().text() || '';
+ const pubDate = parseDate(element.find('.citeurl .cite-date').first().text().trim());
+ return {
+ link,
+ title,
+ description: renderDescription(description, imgs),
+ author,
+ pubDate,
+ };
+ })
+ .toArray()
+ .filter((e) => e?.link);
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ ctx.state.data = {
+ title: `${keyword} - 搜狗搜索`,
+ description: `${keyword} - 搜狗搜索`,
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/sogou/templates/description.art b/lib/v2/sogou/templates/description.art
new file mode 100644
index 0000000000..5f98f4ca33
--- /dev/null
+++ b/lib/v2/sogou/templates/description.art
@@ -0,0 +1,6 @@
+{{@ description }}
+{{if images}}
+ {{each images}}
+
+ {{/each}}
+{{/if}}
diff --git a/website/docs/routes/other.mdx b/website/docs/routes/other.mdx
index ebce0337e7..42aeebd693 100644
--- a/website/docs/routes/other.mdx
+++ b/website/docs/routes/other.mdx
@@ -91,6 +91,12 @@ See [#app-store-mac-app-store](/routes/program-update#app-store-mac-app-store)
2. Copy everything in the URL after `?`, for example: `https://www.autotrader.co.uk/car-search?radius=50&postcode=sw1a1aa&onesearchad=Used&onesearchad=Nearly%20New&onesearchad=New&price-to=9000&year-from=2012&body-type=Hatchback&transmission=Automatic&exclude-writeoff-categories=on` will produce `radius=50&postcode=sw1a1aa&onesearchad=Used&onesearchad=Nearly%20New&onesearchad=New&price-to=9000&year-from=2012&body-type=Hatchback&transmission=Automatic&exclude-writeoff-categories=on`
+## Bing {#bing}
+
+### 搜索 {#bing-sou-suo}
+
+
+
## BOOKWALKERTW {#bookwalkertw}
### 热门新书 {#bookwalkertw-re-men-xin-shu}
@@ -181,6 +187,10 @@ Official Website: [https://news.yahoo.co.jp/pages/article/20200207](https://news
+### Search {#google-search}
+
+
+
## Grand-Challenge {#grand-challenge}
### Challenge 列表 {#grand-challenge-challenge-lie-biao}
@@ -597,9 +607,13 @@ Specify options (in the format of query string) in parameter `routeParams` param
-## 百度热搜 {#bai-du-re-sou}
+## 百度 {#bai-du}
-### 榜单 {#bai-du-re-sou-bang-dan}
+### 搜索 {#bai-du-sou-suo}
+
+
+
+### 热搜榜单 {#bai-du-re-sou-bang-dan}
| 热搜榜 | 小说榜 | 电影榜 | 电视剧榜 | 汽车榜 | 游戏榜 |
@@ -851,10 +865,14 @@ Specify options (in the format of query string) in parameter `routeParams` param
## 搜狗 {#sou-gou}
-### 搜狗特色 LOGO {#sou-gou-sou-gou-te-se-logo}
+### 特色 LOGO {#sou-gou-te-se-logo}
+### 搜索 {#sou-gou-sou-suo}
+
+
+
## 台灣事實查核中心 {#tai-wan-shi-shi-cha-he-zhong-xin}
### 最新相關資訊 / 最新查核報告 {#tai-wan-shi-shi-cha-he-zhong-xin-zui-xin-xiang-guan-zi-xun-zui-xin-cha-he-bao-gao}
diff --git a/website/docs/routes/picture.mdx b/website/docs/routes/picture.mdx
index b86598e338..d0bb94d886 100644
--- a/website/docs/routes/picture.mdx
+++ b/website/docs/routes/picture.mdx
@@ -165,9 +165,9 @@
-## Bing Wallpaper {#bing-wallpaper}
+## Bing {#bing}
-### Daily Wallpaper {#bing-wallpaper-daily-wallpaper}
+### Daily Wallpaper {#bing-daily-wallpaper}