-
Notifications
You must be signed in to change notification settings - Fork 9.8k
feat(route/gettyimages): add Australia image search #21877
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { renderToString } from 'hono/jsx/dom/server'; | ||
|
|
||
| export const renderSearchItemDescription = (imageSrc: string): string => | ||
| renderToString( | ||
| <figure> | ||
| <img src={imageSrc} /> | ||
| </figure> | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import type { Namespace } from '@/types'; | ||
|
|
||
| export const namespace: Namespace = { | ||
| name: 'Getty Images Australia', | ||
| url: 'www.gettyimages.com.au', | ||
| lang: 'en', | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| import type { Cheerio, CheerioAPI } from 'cheerio'; | ||
| import { load } from 'cheerio'; | ||
| import type { Element } from 'domhandler'; | ||
| import type { Context } from 'hono'; | ||
|
|
||
| import { config } from '@/config'; | ||
| import type { DataItem, Route } from '@/types'; | ||
| import { ViewType } from '@/types'; | ||
| import ofetch from '@/utils/ofetch'; | ||
|
|
||
| import { renderSearchItemDescription } from './description'; | ||
|
|
||
| const getTitleFromElement = ($element: Cheerio<Element>): string | undefined => $element.attr('aria-label') || $element.find('img').attr('alt') || $element.text() || undefined; | ||
|
|
||
| const getImageFromElement = ($element: Cheerio<Element>): string | undefined => | ||
| $element.find('img').attr('src') || $element.find('img').attr('data-src') || $element.find('img').attr('data-lazy-src') || $element.find('img').attr('data-image-src'); | ||
|
|
||
| export const route: Route = { | ||
| path: '/search/:keyword', | ||
| categories: ['picture'], | ||
| view: ViewType.Pictures, | ||
| description: | ||
| 'Image search results on the first page only. Radar cannot extract the `phrase` query string; subscribe with `/gettyimages/search/:keyword` manually (e.g. `/gettyimages/search/kangaroo`). The listing does not provide reliable publish dates.', | ||
| url: 'www.gettyimages.com.au', | ||
| example: '/gettyimages/search/kangaroo', | ||
| parameters: { | ||
| keyword: 'Search keyword', | ||
| }, | ||
| features: { | ||
| requireConfig: false, | ||
| requirePuppeteer: false, | ||
| antiCrawler: false, | ||
| supportRadar: true, | ||
| supportBT: false, | ||
| supportPodcast: false, | ||
| supportScihub: false, | ||
| }, | ||
| radar: [ | ||
| { | ||
| source: ['www.gettyimages.com.au/search/2/image'], | ||
| target: '/search/:keyword', | ||
| }, | ||
| ], | ||
| name: 'Search', | ||
| maintainers: ['QwQ-OvO'], | ||
| handler, | ||
| }; | ||
|
|
||
| async function handler(ctx: Context) { | ||
| const keyword = ctx.req.param('keyword'); | ||
| if (!keyword) { | ||
| throw new Error('Missing required parameter: keyword'); | ||
| } | ||
|
|
||
| const baseUrl = 'https://www.gettyimages.com.au'; | ||
| const searchUrl = `${baseUrl}/search/2/image?phrase=${encodeURIComponent(keyword)}`; | ||
|
|
||
| const response = await ofetch<string>(searchUrl, { | ||
| headers: { | ||
| 'User-Agent': config.trueUA, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the site only work when using this exact UA instead of RSSHub's random generated UA? |
||
| }, | ||
| }); | ||
| const $: CheerioAPI = load(response); | ||
|
|
||
| const seen = new Set<string>(); | ||
| const list: DataItem[] = []; | ||
| for (const element of $('a[href^="/detail/"]').toArray()) { | ||
| const $element: Cheerio<Element> = $(element); | ||
| const href = $element.attr('href'); | ||
| if (!href) { | ||
| continue; | ||
| } | ||
|
|
||
| const link = new URL(href, baseUrl); | ||
| link.search = ''; | ||
| link.hash = ''; | ||
| const normalizedLink = link.toString(); | ||
|
|
||
| if (seen.has(normalizedLink)) { | ||
| continue; | ||
| } | ||
| seen.add(normalizedLink); | ||
|
|
||
| const title = getTitleFromElement($element) || normalizedLink; | ||
| const image = getImageFromElement($element); | ||
|
|
||
| list.push({ | ||
| title, | ||
| link: normalizedLink, | ||
| guid: normalizedLink, | ||
| description: image ? renderSearchItemDescription(image) : undefined, | ||
| }); | ||
| } | ||
|
Comment on lines
+65
to
+93
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the number 1 anti-pattern listed in Script Standard.
Comment on lines
+65
to
+93
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the embeded JSON in |
||
|
|
||
| return { | ||
| title: `Getty Images Australia - ${keyword}`, | ||
| link: searchUrl, | ||
| item: list, | ||
| }; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreachable condition.
RSSHub/lib/routes/gettyimages/search.ts
Line 19 in c44afc8
keywordas compulsory path parameter. If one visits the route without it, the request will be rejected by hono with a 404 error.