rsshub
Version:
Make RSS Great Again!
115 lines (99 loc) • 4.13 kB
text/typescript
import { load } from 'cheerio';
import cache from '@/utils/cache';
import ofetch from '@/utils/ofetch';
import g_encrypt from './execlib/x-zse-96-v3';
import md5 from '@/utils/md5';
import { config } from '@/config';
export const header = {
'x-api-version': '3.0.91',
};
const fixImageUrl = (url: string) => url.split('?')[0].replace('_b.jpg', '.jpg').replace('_r.jpg', '.jpg').replace('_720w.jpg', '.jpg');
export const processImage = (content: string) => {
const $ = load(content, null, false);
$('noscript, a[data-draft-type="mcn-link-card"]').remove();
$('a').each((_, elem) => {
const href = $(elem).attr('href');
if (href?.startsWith('http://link.zhihu.com/?target=') || href?.startsWith('https://link.zhihu.com/?target=')) {
const url = new URL(href);
const target = url.searchParams.get('target') || '';
try {
$(elem).attr('href', decodeURIComponent(target));
} catch {
// sometimes the target is not a valid url
}
}
});
$('img.content_image, img.origin_image, img.content-image, img.data-actualsrc, figure>img').each((i, e) => {
if (e.attribs['data-actualsrc']) {
$(e).attr({
src: fixImageUrl(e.attribs['data-actualsrc']),
width: null,
height: null,
});
$(e).removeAttr('data-actualsrc');
} else if (e.attribs['data-original']) {
$(e).attr({
src: fixImageUrl(e.attribs['data-original']),
width: null,
height: null,
});
$(e).removeAttr('data-original');
} else {
$(e).attr({
src: fixImageUrl(e.attribs.src),
width: null,
height: null,
});
}
});
return $.html();
};
export const getCookieValueByKey = (key: string) =>
config.zhihu.cookies
?.split(';')
.map((e) => e.trim())
.find((e) => e.startsWith(key + '='))
?.slice(key.length + 1) || '';
export const getSignedHeader = async (url: string, apiPath: string) => {
// Because the API of zhihu.com has changed, we must use the value of `d_c0` (extracted from cookies) to calculate
// `x-zse-96`. So first get `d_c0`, then get the actual data of a ZhiHu question. In this way, we don't need to
// require users to set the cookie in environmental variables anymore.
// fisrt: get cookie(dc_0) from zhihu.com
const { dc0, zseCk } = await cache.tryGet('zhihu:cookies:d_c0', async () => {
if (getCookieValueByKey('d_c0') && getCookieValueByKey('__zse_ck')) {
return { dc0: getCookieValueByKey('d_c0'), zseCk: getCookieValueByKey('__zse_ck') };
}
const response1 = await ofetch.raw('https://static.zhihu.com/zse-ck/v3.js');
const script = await response1._data.text();
const zseCk = script.match(/__g\.ck\|\|"([\w+/=\\]*?)",_=/)?.[1];
const response2 = zseCk
? await ofetch.raw(url, {
headers: {
cookie: `${response1.headers
.getSetCookie()
.map((s) => s.split(';')[0])
.join('; ')}; __zse_ck=${zseCk}`,
},
})
: null;
const dc0 =
(response2 || response1).headers
.getSetCookie()
.find((s) => s.startsWith('d_c0='))
?.split(';')[0]
.trim()
.slice('d_c0='.length) || '';
return { dc0, zseCk };
});
// calculate x-zse-96, refer to https://github.com/srx-2000/spider_collection/issues/18
const xzse93 = '101_3_3.0';
const f = `${xzse93}+${apiPath}+${dc0}`;
const xzse96 = '2.0_' + g_encrypt(md5(f));
const zc0 = getCookieValueByKey('z_c0');
return {
cookie: `__zse_ck=${zseCk}; d_c0=${dc0}${zc0 ? `;z_c0=${zc0}` : ''}`,
'x-zse-96': xzse96,
'x-app-za': 'OS=Web',
'x-zse-93': xzse93,
};
};