又是与知乎斗智斗勇的一天


在知乎文章页面右键检查,获取文章信息的 api 呼之欲出。

QQ 截图 20200716173734.png

链接如下,其实动手搜索一下的话也可以搜到 知乎 v4API 大全

https://www.zhihu.com/api/v4/members/zhi-hu-you-xi/articles?include=data[*].comment_count,suggest_edit,is_normal,thumbnail_extra_info,thumbnail,can_comment,comment_permission,admin_closed_comment,content,voteup_count,created,updated,upvoted_followees,voting,review_info,is_labeled,label_info;data[*].author.badge[?(type=best_answerer)].topics&offset=20&limit=20&sort_by=created

1.png

可以看出很明显是 json 的格式。外层是pagingdatadata中每一个大括号都是一篇文章,包含updatedauthoris_labeledexcerptadmin_closed_comment等杂七杂八的数据。可以看出excerpt是描述,title是标题,content是正文的全部内容。

{
"paging":{......},
"data":[
    {
    "updated":1594851110,
    ......
    "is_labeled":false,
    "excerpt":"1 未来知乎游戏会推荐一些游戏来做评测,推出评测机制的想法是为了跟玩家们建立更多的链接。参与本次活动获得免费 Steam 游戏 <b>KEY<\/b> ,…",
    "admin_closed_comment":false,
    ......
    "title":"知乎游戏评测:《超凡双生》",
    ......
    "content":"<p>1 未来知乎游戏会推荐一些游戏来做评测,推出评测机制的想法是为了跟玩家们建立更多的链接。参与本次活动获得免费 Steam 游戏 ......"
    "comment_count":13,
    ......
},
......
]
}

为了方便跨平台运行,选择使用 python 对 json 进行解析。不算复杂,用requests库读出 api 的数据, 没安装的话pip install requests,用json库进行解析读出标题和描述和本地文件进行对比,有更新则调用 Server 酱进行通知。

import requests
import json
import os
import sys

reload(sys)
sys.setdefaultencoding('utf-8')
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}
URL="****"
URLReq='https://sc.ftqq.com/S****97.send?text='
res = requests.get(URL,headers=header)
res.encoding = 'utf-8'
Json=json.loads(res.text)
Data=Json['data']
Art1=Data[0]
Text=Art1['excerpt']
Title=Art1['title']
print(Text)

FilePar="temp.txt"
Comp=''
if not os.path.exists(FilePar):
    with open(FilePar,'a+') as file:
        file.write("") 
with open(FilePar,'r') as file:
    Comp=file.read()

if(Comp!=Text):
    requests.get(URLReq+Title+'&desp='+Text)
    print('Has been sent')
    with open(FilePar,'w') as file:
        file.write(Text)

好景不长,刚用 python 重构完,一看日志竟然开始报错了。

QQ 截图 20200716163849.png

打开 api 一看,哦豁凉凉。

{'error': {'code': 10002, 'message': '10002:请求参数异常,请升级客户端后重试'}}

但是有意思的是,到现在知乎 web 端依旧在使用这个 api。

20/8/1

重新写一下,之前的 api 依旧是不可用,与其继续扒拉 Api 不如直接从网页源码入手。

nice

同样是request库读网页源码,记得带上 UA 不然会400BadRequest。读出来之后用正则匹配出第一篇文章的authorNameitemIdtitlearticleBody

注意:在 pytho3.4 版本中才引入html库使用html.unescape(),在 2.7 版本中应改成HTMLParser否则报错AttributeError: 'module' object has no attribute 'unescape'(来自 stackoom.com

import HTMLParser
HTMLParser.HTMLParser().unescape('Hello &amp; World')
# -*- coding: utf-8 -*
import HTMLParser
import requests
import json
import sys
import re
import os

reload(sys)
sys.setdefaultencoding('utf-8')
URL="******"
URLRequ='https://sc.ftqq.com/******.send?text='
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}
match=r'<div class="ContentItem ArticleItem".+?>'
matchJson=r'{.+?}'
matchArti=r'itemProp="articleBody">.+?</span>'
matchArtiBody=r'>.+?…'
res = requests.get(URL,headers=header)
res=res.text
matchObj = re.search(match,res)
if matchObj:
    print(matchObj.group())
    matchObj = re.search(matchJson,matchObj.group())
    if matchObj:
        json=json.loads(HTMLParser.HTMLParser().unescape(matchObj.group()))
        authorName=json['authorName']
        itemId=json['itemId']
        title=json['title']
        articleBody=''
        print(title)
        print(articleBody)

        FilePar="temp.txt"
        Comp=''
        if not os.path.exists(FilePar):
            with open(FilePar,'a+') as file:
                file.write("") 
        with open(FilePar,'r') as file:
            Comp=file.read()

        if(Comp!=title):
            matchObj = re.search(matchArti,res)
            if matchObj:
                matchObj = re.search(matchArtiBody,matchObj.group())
                if matchObj:
                    articleBody=matchObj.group()
            requests.get(URLRequ+title+'&desp='+articleBody)
            print('Has been sent')
            with open(FilePar,'w') as file:
                file.write(title)
else:
    print("no match")