拒绝某度文库,跟我一起用Python写个下载器
Posted python可乐编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拒绝某度文库,跟我一起用Python写个下载器相关的知识,希望对你有一定的参考价值。
度娘啊,你以为你把百度网盘取消限速了,我们就满意了?当然不满意,还有百度文库呢!本来好好的文档,非得不让我们下载……今天,就教大家跟我一起写百度文库下载器Weeker,拒绝文库,从我做起。
我们的下载器是一个GUI程序,具体架构是,先写核心文件(get.py),再写命令行解析文件(weeker.py),接着使用Fire生成命令行,最后用Gooey把CLI转换为GUI。
很多人学习python,不知道从何学起。 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。 很多已经做案例的人,却不知道如何去学习更加高深的知识。 那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码! QQ群:701698587 欢迎加入,一起讨论 一起学习!
准备
安装
- 安装Python 3.8;
- 安装依赖(依赖的作用下文会详解):pip install requests docx beautifulsoup4 Gooey
目录
初始化项目(下面的脚本是在Unix或Linux上运行的):
复制代码 隐藏代码 cd /path/to/project mkdir Weeker touch get.py weeker.py
爬虫核心
第一步,打开get.py,先引入类库:
复制代码 隐藏代码 from os import getcwd, system from re import sub import requests import docx from bs4 import BeautifulSoup
每个模块的作用如下:
由于保存文件时我们需要判断路径,定义一个pwd常量,用来存储“当前路径:
复制代码 隐藏代码
pwd = getcwd()
再声明一个get
url:ua:path:output:convert方法,来实现我们的爬虫函数,其中:
编写get:::::函数
获取html&解析
把光标移到get:::::函数。首先照例我们要用requests,并且祭上bs4一条龙解析:
复制代码 隐藏代码 headers = { \'User-Agent\': ua } result = requests.get(url, headers=headers) soup = BeautifulSoup(res.text, "html.parser") # 为了方便管理文本,我们定义一个数组用来存储文档的每一行 everyline = []
添加标题
我们给文档先添上标题,也就是网页的标题。
复制代码 隐藏代码
everyline.append(soup.title.string)
但是这样会有一个问题,添加出来的标题都是“xxxxxxx_百度文库”,很不雅观。所以抬上re.sub作替换,改成:
复制代码 隐藏代码 everyline.append(re.sub(\'_百度文库\', \'\', soup.title.string, 1))
获取正文
通过观察网页,我们发现,bd doc-reader这个class有重大嫌疑,这个class里的东西都是正文内容:
我们通过bs4解析它,发现内容中有很多\\n、\\x0c和空格,\\n是换行符,我们把它分割到数组中,而后两者分别删除即可:
复制代码 隐藏代码 for doc in soup.find_all(\'div\', attrs={"class": "bd doc-reader"}): everyline.extend(doc.get_text().split(\'\\n\')) # 扩展数组 everyline = [i.replace(\' \', \'\') for i in everyline] everyline = [i.replace(\'\\x0c\', \'\') for i in everyline]
保存文件
接下来就是保存文件。我的思路是,先按照txt格式保存,然后再判断convert参数,如果填写了docx,再将txt加后缀并修改为docx。
复制代码 隐藏代码 final_path = path # 如果是相对路径,连接pwd改成绝对路径,否则python不支持。 if not path.startswith(\'/\'): final_path = pwd + \'/\' + final_path try: file = open(final_path + \'/\' + output, \'w\', encoding=\'utf-8\') for line in everyline: file.write(line) file.write(\'\\n\') file.close() except FileNotFoundError as err: print("wenku: error: Output directory does not exist. Quitting.") exit(1) # 如果有convert请求 if convert == \'docx\': with open(final_path + \'/\' + output) as f: docu = docx.Document() # 创建对象 docu.add_paragraph(f.read()) # 添加段落 docu.save(final_path + \'/\' + output + \'.\' + convert) # 保存文档,文件名为xxx.xxx.docx system(\'rm \' + final_path + \'/\' + output) # 删除try中保存的文件
创建GUI
打开weeker.py。
首先是两句 import,其中Gooey可以用类似argparse的语法将CLI转换为GUI。
复制代码 隐藏代码 from gooey import Gooey, GooeyParser import get
接着添加if __name__ == \'__main__\':
复制代码 隐藏代码 if __name__ == \'__main__\': main() 我们来定义一下这个main():
复制代码 隐藏代码 @Gooey(encoding=\'utf-8\', program_name="Weeker ", language=\'chinese\') def main(): parser = GooeyParser(description="百度文库下载器,干杯!") parser.add_argument("url", metavar=\'文档地址\', widget="TextField") parser.add_argument("ua", metavar=\'用户UA\', widget="Dropdown", choices={"Googlebot": 1, \'Baiduspider\': 2}) parser.add_argument("path", metavar=\'保存路径\', widget="DirChooser") parser.add_argument("output", metavar=\'重命名\', widget="TextField") parser.add_argument("convert", metavar=\'格式转换\', widget="Dropdown", choices={\'docx\': 1}) args = parser.parse_args() get.get(args.url, ua=args.ua, path=args.path, output=args.output, convert=args.convert)
@Gooey是一个修饰器,可以把main()转换为一个Gooey函数。在main中,我们写下类似argparse的parser.add_argument函数,最终定义args = parser.parse_args(),从args的成员获取每个参数的输入,传到get.py里。我们运行一下,神奇的一幕发生了:
我们成功地把CLI转换成了GUI!!!
注I:如果你喜欢命令行,可以GitHub搜python-fire,直接将函数和参数暴漏给CLI,效果更佳。
注II:因为电脑原因,打包不了成品,因此有需要者请自行编译。
注III:附件里有两个py文件。
注IV:我刚看见源码里面有一句import写错了,如果你下载了源码,请先照文中代码核对一下。
文本选中复制
文本选中复制
某些网站例如某度文库、道客某某等都不允许用户选中文本进行复制,作为一个搞前端的,就感觉离谱,文本都下载到本地了,还不让我复制,于是为了更好的学(复)习(制),实现了一个脚本去解决这些限制。
描述
首先来看一下效果图,依旧是以某度文库、道客某某为例展示效果,点击复制按钮即可成功复制。
脚本下载地址:https://greasyfork.org/scripts/405130-文本选中复制
Github:https://github.com/WindrunnerMax/TKScript/blob/master/文本选中复制.js
脚本主要支持 百度文库 道客巴巴 无忧考网 学习啦 蓬勃范文 中文本的复制
实现
在研究实现之前,可能需要知道下面的一些知识,后面的链接是我之前写过的一些博客:
某度文库
在某度文库中直接右击检查元素的话,是能够直接看到文字的,可以直接在调试面板的Elements
审查元素中复制,但是总是有些麻烦。如果在选中某度文库的东西会弹出他自行插入的复制按钮,无论是按Ctrl+C
或者点击他的复制按钮都无效,除非开通一个VIP
,本着白嫖的原则,且文本都下载到浏览器了还不让复制有点说不过去,于是首先研究一下他的Event Listeners
。
虽然通过移除一些Event Listeners
确实能够达到使用Ctrl+C
来实现复制的效果,但是浏览器并不提供获取所有事件监听的方法,无法移除对于匿名的事件处理函数,对于具名的事件处理函数也不容易获取,谷歌浏览器提供的getEventListeners
方法也只能在Console
中使用,在脚本中会出现找不到该方法的异常,于是替换了一种方案,通过自行实现一个复制按钮来规避某度文库对于按键以及复制事件的屏蔽,具体是通过动态地插入Dom
实现一个按钮,然后使用ClipboardJS
这个插件去实现复制,其他的操作都是一些细节的处理,例如阻止这个插入的按钮继续冒泡触发onmouseup
事件等。
道客某某
不得不说,这个真的是惊到我了,他的实现是将文本加密,然后解密文本,最后通过使用Canvas
将文本绘制,拖动鼠标选中时其实只是通过事件监听动态的插入了一个淡蓝色的透明的div
,看似是选中了,实际文本是并未选中的。
见招拆招,既然文本都已经下载到了我本地,那么他的解密方式也必定在本地,于是我首先寻找的就是他对于加密的数据进行解密的代码,在浏览器中debug
了很长时间,因为他对于代码有加密混淆压缩的行为,解密的相关代码比较混乱,并不太容易去复现,于是我换了一个思路,既然VIP
是能够复制的,那么对于这个点击复制的按钮一定会有相应的事件处理函数,那么就寻找这个按钮绑定的事件处理函数,通过不断地debug
我定位了一个加密的Js
文件,虽然做了加密以及混淆但是将其解析并格式化之后在事件处理函数的部分不是特别影响阅读,此外他的混淆的变量名是动态生成的,所以要做的就是再次请求一遍这个Js
首先将其解析生成一段字符串然后通过正则表达式匹配正确的变量名,从而实现文本的复制。
其他
对于这一部分基本上都是通过监听一个oncopy
事件去拦截复制操作,对于DOM0
级模型直接将oncopy
事件的处理函数指向一个空函数即可,对于DOM2
级模型,前文提到无法在脚本中直接获取一个元素绑定的所有事件,通过观察这些网站的Event Listeners
可以发现其绑定的oncopy
事件都是绑定在document
上的,而且都是冒泡模型,那么只需要阻止事件向上冒泡就能规避这些网站的oncopy
事件的触发,实现方案就是在body
上定义oncopy
事件为一个空函数并阻止其向上冒泡。
Github
https://github.com/WindrunnerMax/TKScript
以上是关于拒绝某度文库,跟我一起用Python写个下载器的主要内容,如果未能解决你的问题,请参考以下文章