[分享] 批量检查 DEVONthink 中的 知乎链接是否已经失效

原问题

[求助] 我有很多知乎链接,如何用「自动化工具」检查这些链接是否已经失效?

问题已解决,见 [分享] 批量检查 DEVONthink 中的 知乎链接是否已经失效 - #7,来自 Smuggler4294


求助内容

朋友们,我有很多知乎链接,如何用「自动化工具」检查这些链接是否已经失效?

困境

已知,知乎的无效链接都包含「你似乎来到了没有知识存在的荒原」,我便以此为「特征」,写了一个小程序。
具体的实现思路是:

  • 用 curl 抓取链接后的 html,
  • 然后检查 html 中是否包含「没有知识存在的荒原」字样,如果有,则判定「该链接已经失效」。

这个小程序曾经运行良好,直到:最近知乎更新了反爬策略,目前 curl 抓取的 html 内容都是混淆代码。因此,「没有知识存在的荒原」这个「特征」不可行了。

我的尝试

我准备了一些「已经失效的」和「仍然有效的」知乎网页。

我用 curl 抓取他们的内容,尝试对比,寻找新的「特征」。但是没有看出门道。

以下是几个「已经失效」的网页链接

以下是几个「仍然有效」的网页链接

求助

请问,如今,「用 “自动化工具” 检查这些链接是否已经失效」,还能有什么思路呢?


备注

「自动化工具」不限于 curl,其他的 Python、Ruby、Shell Script、AppleScript、Keyboard Maestro、Alfred 等也可以。

附录

除了 html 代码混淆,知乎还有其他的反爬虫机制。触发后,需要验证自己是真人而非机器人。此时需要点点鼠标,解除验证。

检验自己是否触发「反爬验证」的方法是:

我基本不用知乎,只能给出一猜想:考察 curl 所得文件的体积,如果小于某个阈值,可能就意味着对应的网页失效了。

我尝试了这个思路

用 curl 抓取文章后

curl https://www.zhihu.com/question/627881075/answer/3265216595 > zhihu_deleted_01.html
curl https://www.zhihu.com/question/634274464/answer/3324202207 > zhihu_deleted_02.html
curl https://www.zhihu.com/question/639896957/answer/3366712624 > zhihu_deleted_03.html
curl https://www.zhihu.com/question/633547293/answer/3316044298 > zhihu_deleted_04.html

curl https://www.zhihu.com/question/656230250/answer/3509502697 > zhihu_alive_01.html
curl https://www.zhihu.com/question/26854682/answer/213351790 > zhihu_alive_02.html
curl https://zhuanlan.zhihu.com/p/353187472 > zhihu_alive_03.html

接着,用 ls -lh 查看文件大小,发现,文件大小并无明显差异。

建议打开看一下你抓到的东西,凭直觉,这个大小可能意味着你根本没有抓到任何东西……

建议打开看一下你抓到的东西,凭直觉,这个大小可能意味着你根本没有抓到任何东西……

的确,我也这样猜想。

对比两个文件后我发现,第 25 行的超长代码长度不一样。

但是,这似乎是混淆代码,我不知道如何解析其含义。

我用 zhihu API 解决这个问题了

方法

  • 对于「回答」
    • 原始链接 https://www.zhihu.com/question/656230250/answer/3509502697
    • 可替换为 https://www.zhihu.com/api/v4/answers/3509502697
  • 对于「问题」
    • 原始链接 https://www.zhihu.com/question/23434442
    • 可替换为 https://www.zhihu.com/api/v4/questions/23434442
  • 对于「专栏/文章」
    • 原始链接 https://zhuanlan.zhihu.com/p/180071279
    • 可替换为 https://www.zhihu.com/api/v4/articles/180071279
  • 对于「想法」
    • 原始链接 https://www.zhihu.com/pin/1792345730800824320
    • 可替换为 https://www.zhihu.com/api/v4/pins/1792345730800824320

实践

# 定义原始 URL
originalURL='https://www.zhihu.com/question/656230250/answer/3509502697'

# 用「正则表达式」,从连接中,截取最后一个斜杠 `/` 后的数字。
itemID=$(echo "$originalURL" | awk -F'/' '{print $NF}')

# 将这个数字拼贴到 `https://api.zhihu.com/appview/api/v4/answers/` 后面
convertedURL="https://api.zhihu.com/appview/api/v4/answers/$itemID"

# 并用 `curl` 获取新的 URL 的内容。
curl "$convertedURL"

如果 最后一步的输出包含「荒原」那么原文已删除。

用 Keyboard Maestro 批量检查 DEVONthink 中的 zhihu 链接是否已经失效

配置 Keyboard Maestro

  1. 创建一个 Macro,不妨命名为 check zhihu 404
  2. 配置一个激活方式,例如快捷键。
  3. 添加 Execute AppleScript 作为 Action
  4. 配置 Execute AppleScript
    • 选择 Execute text script
    • 选择 Ignore results
    • 在 Script 中填入下面内容
-- Import helper library
tell application "Finder" to set pathToAdditions to ((path to application id "DNtp" as string) & "Contents:Resources:Template Script Additions.scpt") as alias
set helperLibrary to load script pathToAdditions

-- Get the selection
tell application id "DNtp" to set thisSelection to the selection

-- Error handling
if thisSelection is {} then error localized string "Please select a document or group, then try again."
-- if (length of thisSelection) > 1 then error localized string "Please select only one document or group, then try again."

tell application id "DNtp"
	set theTag404 to {"荒原"}
	
	repeat with theRecord in thisSelection
		set originalURL to URL of theRecord
		set theTags to tags of theRecord
		set theTitle to name of theRecord
		
		if (originalURL contains "zhihu.com") and (not (theTags contains theTag404)) then
			-- 如有必要, 调整 delay 参数以减缓触发 Zhihu 的反爬
			delay 1
			
			-- Extract itemID
			set itemID to do shell script "echo " & quoted form of originalURL & " | awk -F'/' '{print $NF}'"
			-- display dialog itemID

			-- Convert to zhihuAPI
			if (originalURL contains "question") then
				if (originalURL contains "answer") then
					-- 回答
					set convertedURL to "https://www.zhihu.com/api/v4/answers/" & itemID
				else
					-- 问题
					set convertedURL to "https://www.zhihu.com/api/v4/questions/" & itemID
				end if
			else if (originalURL contains "zhuanlan") then
				-- 专栏
				set convertedURL to "https://www.zhihu.com/api/v4/articles/" & itemID
			else if (originalURL contains "pin") then
				-- 想法
				set convertedURL to "https://www.zhihu.com/api/v4/pins/" & itemID
			end if
			-- display dialog convertedURL
			
			-- check the URL using Zhihu API
			set urlContent to do shell script "curl " & quoted form of convertedURL
			
			-- display dialog urlContent
			
			if (urlContent contains "系统监测到您的网络环境存在异常") then
				display dialog "⚠️检测到「知乎反爬验证」,请前往 zhihu.com 人工验证。
程序终止于 《" & theTitle & "》条目"
				exit repeat
			else if (urlContent contains "没有知识存在的荒原") then
				set tags of theRecord to theTags & theTag404
				-- display dialog "The original post is dead. " & originalURL
			else
				-- display dialog "the URL is still alive"
			end if
		end if
	end repeat
	display dialog "Check zhihu 404 Completed"
end tell

在 DEVONthink 中使用

  1. 选中一些来自知乎的条目( URL 来自 zhihu.com
  2. 用快捷键调用上面的 Macro
1 个赞