百度文库之文档解析笔记

起因
上次想下载个文档,试了一圈百度文库下载器,结果都不能用了。
包括各种软件和浏览器插件、油猴插件,全都不行了。
无奈只能临时用复制的方法(选中内容,点击“翻译”)把内容拿到。
事后有空,索性看看能不能解析下载下来。
过程
先网上搜了一下,有开源的内容,也有分析的文章,试了两个也都不能用了,所以没细看。
直接上手,发现直接访问文章链接,网页内容直接就包括所有需要的东西了,包括文字和图片的链接。
其中图片链接不知道怎么解析的,看起来像是服务端把多张图片合并成了一张返回,前端再分割的。
文字内容是json格式返回的,网上搜了一下,有个传说中的bdjson,也就是百度自定义的json格式,也就是xreader(psp上的阅读软件)的格式,简单查了一下,没发现xreader转doc的方法,索性放弃直接转换,决定直接取文字内容算了,之后再把图片全部下载,手动调整格式。
可能很多时候只是想复制一点内容,却发现无法预览全文,测试发现,先清空文库的cookie,再从百度搜索界面跳转文档,就不限制全文预览了。
【百度文库之文档解析笔记】后来又发现一个接口,直接可以预览全文,可以复制,就是不能打印(只显示6页内容,其他部分空白)

https://wenku.baidu.com/share/文档ID?share_api=1

下载文字和图片的代码
import requests import re, time, os, jsonclass 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()

    推荐阅读