起因
上次想下载个文档,试了一圈百度文库下载器,结果都不能用了。
包括各种软件和浏览器插件、油猴插件,全都不行了。
无奈只能临时用复制的方法(选中内容,点击“翻译”)把内容拿到。
事后有空,索性看看能不能解析下载下来。
过程
先网上搜了一下,有开源的内容,也有分析的文章,试了两个也都不能用了,所以没细看。
直接上手,发现直接访问文章链接,网页内容直接就包括所有需要的东西了,包括文字和图片的链接。
其中图片链接不知道怎么解析的,看起来像是服务端把多张图片合并成了一张返回,前端再分割的。
文字内容是json格式返回的,网上搜了一下,有个传说中的bdjson,也就是百度自定义的json格式,也就是xreader(psp上的阅读软件)的格式,简单查了一下,没发现xreader转doc的方法,索性放弃直接转换,决定直接取文字内容算了,之后再把图片全部下载,手动调整格式。
可能很多时候只是想复制一点内容,却发现无法预览全文,测试发现,先清空文库的cookie,再从百度搜索界面跳转文档,就不限制全文预览了。
后来又发现一个接口,直接可以预览全文,可以复制,就是不能打印(只显示6页内容,其他部分空白)
https://wenku.baidu.com/share/文档ID?share_api=1
下载文字和图片的代码
import requests
import re, time, os, json
class Doc(object):
"""
百度文库下载为TXT
"""
def __init__(self, url):
"""
传入地址
"""
self.doc_id = re.findall('view/(.*).html', url)[0]
self.s = requests.session()
self.get_info()
self.get_token()
if not os.path.exists('下载'):
os.mkdir('下载')
@staticmethod
def get_timestamp(long: int = 13):
"""
取时间戳,默认13位
"""
return str(time.time_ns())[:long]
def get_info(self):
"""
取文档名称/页数等基本信息
"""
url = f'https://wenku.baidu.com/share/{self.doc_id}?share_api=1'
try:
html = self.s.get(url).content.decode('GBK')
self.title = re.search(r"title' : '([\s\S]*?)',", html).group(1)
pages = re.search(r"totalPageNum' : '([\s\S]*?)',", html).group(1)
self.pages = int(pages)
self.type = re.search(r"docType' : '(.*?)',", html).group(1)
htmlURLs = re.search(r"htmlUrls: '([\s\S]*?)',", html).group(1).replace('\\\\', '')
htmlURLs = htmlURLs.encode('latin1').decode('unicode_escape')
self.urls = json.loads(htmlURLs)
except:
print('获取文档基本信息失败,运行结束。')
os._exit()
def get_token(self):
"""
取Token,短期(小时级)有效
"""
url = 'https://wenku.baidu.com/api/interface/gettoken?host=wenku.baidu.com&secretKey=6f614cb00c6b6821e3cdc85ab1f8f907'
try:
res = self.s.get(url).json()
self.token = res['data']['token']
except:
print('获取token失败,运行结束。')
os._exit()
def download_pic(self):
"""
下载所有图片
"""
pics = self.urls['png']
for pic in pics:
content = self.s.get(pic['pageLoadUrl']).content
with open(f'下载/{self.title}_{pic["pageIndex"]}.png', 'wb') as f:
f.write(content)
def download(self):
"""
下载文字
"""
self.download_pic()
print(self.token, self.title, self.pages, self.type)
result = ''
url = 'https://wenku.baidu.com/api/interface/getcontent'
for page in range(1, self.pages + 1):
params = {
"doc_id": self.doc_id,
"pn": page,
"t": "json",
"v": "6",
"host": "wenku.baidu.com",
"token": self.token,
"type": "xreader"
}
res = self.s.get(url, params=params).json()
lst = res['data']['1']['body']
for index in range(len(lst)):
if lst[index]['t'] == 'word':
text = lst[index]['c']
if text == ' ' and index < len(lst) - 1:
if lst[index]['p']['y'] < lst[index + 1]['p']['y']:
text = '\n'
else:
text = ' '
result += text
elif lst[index]['t'] == 'pic':
pass
with open(f'下载/{self.title}.txt', 'w', encoding='utf-8') as f:
f.write(result)
print('完成')
def download2(self):
"""
下载文字
"""
self.download_pic()
print(self.token, self.title, self.pages, self.type)
result = ''
pages = self.urls['json']
for page in pages:
res = self.s.get(page['pageLoadUrl']).text
res = res[8:-1]
res = json.loads(res)
lst = res['body']
for index in range(len(lst)):
if lst[index]['t'] == 'word':
text = lst[index]['c']
if text == ' ' and index < len(lst) - 1:
if lst[index]['p']['y'] < lst[index + 1]['p']['y']:
text = '\n'
else:
text = ' '
result += text
elif lst[index]['t'] == 'pic':
pass
with open(f'下载/{self.title}.txt', 'w', encoding='utf-8') as f:
f.write(result)
print('完成')
if __name__ == "__main__":
# url = 'https://wenku.baidu.com/view/81bbd69a541810a6f524ccbff121dd36a22dc477.html'
url = 'https://wenku.baidu.com/view/c145899e6294dd88d1d26b0e.html'
doc = Doc(url)
doc.download()
# doc.download2()