import axios from "axios"; import { WbPlatform } from "../entities/platform"; import { Spilder, SpilderError } from "./spilder"; export class ZhihuSpilder extends Spilder { createTopicArticleLongTextDetail(id: string): Promise { throw new SpilderError(-200, `暂不支持知乎`) } createAccount(uid: number): Promise { throw new SpilderError(-200, `暂不支持知乎`) } loadChildComments(id: number, uid: number): Promise { throw new SpilderError(-200, `暂不支持知乎`) } loadMoreChildComments(id: number, uid: number, max_id: number): Promise { throw new SpilderError(-200, `暂不支持知乎`) } loadMoreComments(id: number, uid: number, max_id: number): Promise { throw new SpilderError(-200, `暂不支持知乎`) } loadComments(id: number, uid: number): Promise { throw new SpilderError(-200, `暂不支持知乎`) } createTopicDetail(link: string): Promise { throw new SpilderError(-200, `暂不支持知乎`) } createTopicArticlePageLinks(link: string): Promise { throw new SpilderError(-200, `暂不支持知乎`) } createTopicArticleLinks(page: string): Promise { throw new SpilderError(-200, `暂不支持知乎`) } createTopicArticleDetail(link: string): Promise { throw new SpilderError(-200, `暂不支持知乎`) } async createTopicPageLinks(keyword: string): Promise<{ links: string[]; keyword: string; count: number; }> { const url = `https://www.zhihu.com/api/v4/search_v3?gk_version=gz-gaokao&t=topic&q=${encodeURIComponent(keyword)}&correction=1&offset=0&limit=20&filter_fields=&lc_idx=0&show_all_topics=1&search_source=Normal` return { links: [ url ], keyword, count: 1 } } createTopicLinks(link: string): Promise<{ list: string; detail: string; }[]> { throw new SpilderError(-200, `暂不支持知乎`) } async loginSuccess(): Promise { if (this.page) { try { await this.page.waitForNavigation(); } catch (e) { } return this.updateLoginInfo(); } } async checkScanStatus(): Promise { // div.Qrcode-content.Qrcode-success > p.Qrcode-scanResultTips if (this.page) { try { const tip = await this.page.waitForSelector('div.Qrcode-content.Qrcode-success > p.Qrcode-scanResultTips', { timeout: 1000 }) if (tip) { const txt = await this.page.$eval('div.Qrcode-content.Qrcode-success > p.Qrcode-scanResultTips', (p) => { return (p as HTMLParagraphElement).innerText; }); return txt; } else { throw new Error(`获取扫码信息失败`) } } catch (e: any) { console.log(e.message) throw e; } } } async setCookies(cookies: any[]): Promise { const page = await this.browser.newPage(); await page.setCookie(...cookies); await page.close(); } async isLogin(): Promise { const cookies = this.platform.cookies; return axios.get(`https://www.zhihu.com/api/v4/me?include=visits_count%2Cdraft_count`, { headers: { cookies: this.cookies } }).then(res => res.data).then(data => { return !!data }).catch(e => { return false; }) } private async updateLoginInfo() { if (this.page) { return this.platform; } } async createLoginQrCode(): Promise { const url = `https://www.zhihu.com/`; const ctx = this.browser.defaultBrowserContext(); await ctx.overridePermissions(url, ['geolocation']) const isLogin = await this.isLogin(); console.log(`createLoginQrCode:${isLogin}`) if (isLogin) { return; } if (!this.page) { return; } this.page.setJavaScriptEnabled(true); this.page.setRequestInterception(true); this.page.setViewport({ width: 1920, height: 768 }); this.page.on('request', async (e) => { const url = e.url(); if (url.startsWith(`https://www.zhihu.com/api/v4/me?include`)) { const cookies = await this.getPageCookies(); await axios.get(url, { headers: { cookie: cookies.map(c => `${c.name}=${c.value}`).join(';') } }).then(res => res.data).then((res: any) => { this.platform.uid = res.uid; this.platform.nickname = res.name; this.platform.status = 1; this.platform.cookies = cookies; return this.db.manager.save(WbPlatform, this.platform); }).catch(e => { const response = e.response; console.error({ data: response.data, cookies }) }) } e.continue().catch(e => { }); }); try { await this.page.goto(url, { waitUntil: ['networkidle2'] }); await this.delay(20); const href = this.page.url(); console.log({ href }) if (href === 'https://www.zhihu.com') { await this.updateLoginInfo(); throw new SpilderError(200, '账号已登录') } if (href.startsWith('https://www.zhihu.com/signin')) { } else { /** * 先跳转拿到cookie */ await this.page.waitForNavigation(); throw new Error(`获取登录二维码失败`) } const img = await this.page.waitForSelector('div.Qrcode-content > div.Qrcode-img > img.Qrcode-qrcode').catch(e => { return null; }); if (!img) { throw new Error(`获取登录二维码失败`) } let loginImage = await this.page.$eval('div.Qrcode-content > div.Qrcode-img > img.Qrcode-qrcode', (img) => (img as HTMLImageElement).src); return loginImage; } finally { // await p.close(); } } async getPageCookies() { if (!this.page) { return []; } return this.page.cookies('https://www.zhihu.com/') } }