裁判文书网

裁判文书网

爬取动态加载的数据(js加密eval,jsfuck )

分析网页

1.打开首页

[外链图片转存失败(img-sFgp9WYn-1566049211688)(E:\CSDN 博客\裁判文书网\首页.png)]
在这里插入图片描述
从各个标签入手,当点击其中一个分类,刑事案件的时候,会跳转到下一个页面,那么可以知道,在这个页面我们要获取到的信息就是各级标签的url

   start_urls = ['http://wenshu.court.gov.cn/']def parse(self, response):'''解析出案件类型的url'''str1 = response.body.decode('utf-8')case_urls = re.findall(r'''<li class="zhuye"><a href="/Index">首页</a></li>(.*?)<li class="yuyan"><a id="yuyan_a"''',str1, re.S)[0]case_url = re.findall(r'''<li><a href="(.*?)" target="_blank">''',case_urls, re.S)[0:1]for urls in case_url:url = 'http://wenshu.court.gov.cn' + urlsyield scrapy.Request(url=url,callback=self.case_links,)

2.打开下一页面后,发现该页面的数据都是ajex动态加载出来的,所以要从该页面重新发送一个请求,来获取信息

,分析后发现,该请求是POST,并且里面的数据都是加密的,需要去获取js信息破解出需要的信息[外链图片转存失败(img-po5Xr6dr-1566049211690)(E:\CSDN 博客\裁判文书网\动态加载的数据信息.png)]
在这里插入图片描述
这里我们需要的参数为 guid ,vl5x ,param

直接在浏览器中搜索对应的参数名,筛选查找出来的js文件,定位到有效信息

vl5x很直观的可以从cookies里看出来和cookies里的vjkl5很像

[外链图片转存失败(img-v0sPjRfd-1566049211690)(E:\CSDN 博客\裁判文书网\获取cookies.png)]
在这里插入图片描述

[外链图片转存失败(img-7s6b0i62-1566049211690)(E:\CSDN 博客\裁判文书网\vl5x.png)]
在这里插入图片描述

[外链图片转存失败(img-AEa4zuWx-1566049211691)(E:\CSDN 博客\裁判文书网\guid vl5x.png)]
在这里插入图片描述

[外链图片转存失败(img-Zgr2LHIE-1566049211691)(E:\CSDN 博客\裁判文书网\get_key()].png)
在这里插入图片描述

在Lawyee.CPWSW.ListExtend.js文件中,发现了getKey函数的定义

在getKey函数的定义中,发现eval()函数,该函数是对js代码进行加密的函数,所以需要对eval()函数进行还原

百度一下就能找到eval()解密的网址https://wangye.org/tools/scripts/eval/

解密的步骤:

a.发现有些eval函数里面还有一层,所以有些需要解密两次,从外向里进行替换,例如eval(de("eval(_fxxx( 先替换de,然后解密,在替换_fxxx,再解密;这里的de和_fxxx我们可以从Lawyee.CPWSW.ListExtend.js文件中找到,_fxxx

b.将以上所有解码的函数存放在一个自己建的js文件中,

c.除此以外还发现在解码得到的的函数中还用到了其他的js(md5.js、base64、sha1.js),我们直接在浏览器中搜索既可以直接找到,并将它们一起放到自己建的js文件中

在解码的最后果然发现了[外链图片转存失败(img-LpgSUboq-1566049211691)(E:\CSDN 博客\裁判文书网\vj联系.png)]

所以我们我们就明白了vl5x的来源了,其实就是gek_key(vjkl5)只不过get_key被加密了

获取vjkl5代码

    def  case_links(self,response):str1 = response.body.decode('utf-8')param = re.findall(r'\+AJLX\+\+(.*)', response.url)[0]param = urllib.parse.unquote(param)# 获取到cookies里的vjkl5vjkl5 = response.headers.getlist('Set-Cookie')[0].decode().split(';')[0].split('=')[1]

求出vl5x的值(这里需要使用execjs执行js代码,wenshu.js就是我们存放get_key()解码得到的js代码及其他js文件的文件)

        js_content = open('D:\python练习\wenshu\wenshu\wenshu.js', encoding='utf8').read()# js_obj = execjs.compile #(js_content)返回一个js对象,该对象包含了js运行的环境。# 再使用js对象调用call()函数。# call('getKey', vjkl5)   #参数1-要执行的js文件中对应的函数,参数2-给调用函数传递的参数。vl5x = execjs.compile(js_content).call('getKey', vjkl5)

guid 的js代码并没有与加密,直接copy执行就可以了

def get_guid(self):guid = self.creat_guid() + self.creat_guid() + "-" + self.creat_guid() + "-" + self.creat_guid() + self.creat_guid() + "-" + self.creat_guid() + self.creat_guid() + self.creat_guid();return guiddef creat_guid(self):return execjs.eval('(((1 + Math.random()) * 65536) | 0).toString(16).substring(1)')

3.发送post请求后就可以获取到文书的列表信息了,接下来就是获取到文书的详情,这里需要注意的是url里面的DocID的值也是被加密的,直接在浏览器里面搜索DocID

[外链图片转存失败(img-Vgy3NYkz-1566049211692)(E:\CSDN 博客\裁判文书网\docid4.png)]
在这里插入图片描述

[外链图片转存失败(img-uEiQBnhb-1566049211693)(E:\CSDN 博客\裁判文书网\docid1.png)]
在这里插入图片描述

这里直接发现了Navi函数,以及他需要的参数key就是获取到的文书列表里面的 “文书ID”信息

搜索Navi函数[外链图片转存失败(img-lhoERS8Y-1566049211693)(E:\CSDN 博客\裁判文书网\navi.png)]
在这里插入图片描述

[外链图片转存失败(img-VsSWqny0-1566049211693)(E:\CSDN 博客\裁判文书网\unzip.png)]
在这里插入图片描述

本以为直接执行js既可以的但是,发现没有那么简单,在分析后发现其实他是需要一个秘钥来解密的,在unzip的函数里发现 这里用的是AES的加密方式 ,

encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})

所以我们需要获得他的秘钥,及_KEY这里的key是默认的,但是尝试了以后发现并不可行,那么我们就需要去找这个秘钥的来源,这个秘钥一定是要和加密的秘钥一样那么要想在浏览器中解密,服务器一定会返回一个秘钥回来,在得到的信息在里发现除了文书ID外还有一个参数RunEval并且一直在变,所以就大胆猜测,这个就是

a.把RunEval带入unzip函数后得到

# 构建js的执行对象 执行js文件中的decode函数
runeval = execjs.compile(js_content).call('decode',runEval)
# 正则筛选出被JSFUCK加密的获取变量值得代码

[外链图片转存失败(img-iufgQ7wJ-1566049211694)(E:\CSDN 博客\裁判文书网\jsfuck.png)]
在这里插入图片描述

这是一段被jsfuck加密的js代码,可以自行百度获取更多关于jsfuck的知识

分析这段代码

$hidescript=string,fromCharCode,

这是一个赋值语句,并且后面有大量的$hidescript出现,直接运行这段代码也获得了对应的值,

在jsfuck的代码中还有_=“constructor”; _ [ _ ] [ _ ]()这个函数,也正是这个函数里面需要$hidescript

所以把前面获得的值带入到函数中我就获得了str_keyde 值,这也就是我们需要的秘钥

runeval = execjs.compile(js_content).call('decode',runEval)
# 正则筛选出被JSFUCK加密的获取变量值得代码
js_key = '$hidescript='+re.findall(r'\$hidescript=(.*?)_="constructor"',runeval)[0]
# 构建js执行对象
ctx = execjs.compile('''function js_KEY(){return %s}''' % js_key)
# 执行js代码 获取$hidescript的值
ctx_key = ctx.call("js_KEY")
print(ctx_key)
#这里需要将"进行转义
ctx_key = '"'+ctx_key.replace('._KEY=','._KEY=\\')+'"'
# 正则筛选出被JSFUCK加密的获取str_key函数的js代码,其中需要先获取到$hidescript的值
js_str_key = re.findall(r'''_="constructor";_\[_\]\[_\](.*?)\(\);''',runeval)[0]
# 将$hidescript替换成他的真实值
js_str_key = js_str_key.replace('$hidescript',ctx_key)
# 构建js执行对象
str_key = execjs.compile('''function js_KEY(){return %s}''' % js_str_key)
# 执行 js 获取str_key
str_key = str_key.call("js_KEY")
print(str_key)

运行结果

Tm('._KEY="452318096;,*Mh)
setTimeout('com.str._KEY="44cb5235f18c40d2a9896101d0169d1d";',8000*Math.random());

接下来就可以直接带入js获取doc_id了

          for doc_id in doc_ids:# 构建js的执行对象 执行js文件中的Navi函数real_id = execjs.compile(js_content).call('Navi', doc_id, real_str_key)print(real_id)

结果

029bb843-b458-4d1c-8928-fe80da403cfe
f08d44ee-b647-11e3-84e9-5cf3fc0c2c18
eff7f53c-b647-11e3-84e9-5cf3fc0c2c18
f074f302-b647-11e3-84e9-5cf3fc0c2c18
f08d1d40-b647-11e3-84e9-5cf3fc0c2c18
508508aa-f317-4845-b560-a178bc4245d4
e05ad449-e7cf-4f5c-8b21-711351599674
cb564602-23aa-46e3-abe3-841f59727e0f
2aae74eb-3c59-42ad-95d7-85d683249c6b
75542beb-5da3-4926-9330-a5948f2b629f

完整代码

spider.py

# -*- coding: utf-8 -*-
# @Time     : 2019/8/8 11:19
# @Author   : lsc
# @Site     ; 
# @File     : wenshu_spider.py
# @Software : PyCharm
import scrapy
import urllib.parse
import re
import execjs
import osimport timeclass WenshuSpider(scrapy.Spider):name = 'wenshu'# 要注意这个地方# allowed_domains = ['wenshu.court.gov.cn/']start_urls = ['http://wenshu.court.gov.cn/']def parse(self, response):'''解析出案件类型的url'''str1 = response.body.decode('utf-8')# print(str1)print('==========================================================')case_urls = re.findall(r'''<li class="zhuye"><a href="/Index">首页</a></li>(.*?)<li class="yuyan"><a id="yuyan_a"''',str1, re.S)[0]case_url = re.findall(r'''<li><a href="(.*?)" target="_blank">''',case_urls, re.S)[0:1]for urls in case_url:url = 'http://wenshu.court.gov.cn' + urlsyield scrapy.Request(url=url,callback=self.case_links,)def  case_links(self,response):print('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')str1 = response.body.decode('utf-8')param = re.findall(r'\+AJLX\+\+(.*)', response.url)[0]param = urllib.parse.unquote(param)# 获取到cookies里的vjkl5vjkl5 = response.headers.getlist('Set-Cookie')[0].decode().split(';')[0].split('=')[1]print(vjkl5)js_content = open('D:\python练习\wenshu\wenshu\wenshu.js', encoding='utf8').read()# js_obj = execjs.compile #(js_content)返回一个js对象,该对象包含了js运行的环境。# 再使用js对象调用call()函数。# call('getKey', vjkl5)   #参数1-要执行的js文件中对应的函数,参数2-给调用函数传递的参数。vl5x = execjs.compile(js_content).call('getKey', vjkl5)# print(vl5x)meta = self.get_metas(index='1', page='10', param=param, vl5x=vl5x,)# print(meta)url = 'http://wenshu.court.gov.cn/List/ListContent'# FormRequest: 发送POST请求的类。# Request: 默认发送GET请求,method设置请求方法。# 由于在请求列表页接口时,cookie中vjkl5的值每次都是变化的,所以在请求时,需要将从response的Set-Cookie中获取的vjkl5的值更换一下,否则使用同一个vjkl5的值,会出现 'remind key' 错误。# urllib/requests: Cookie的自动化管理(cookiejar)?为什么要自动化管理,而不手动去解析?# 1. 复杂,每一个请求的响应都要去提取并存储;# 2. 容易遗漏;# scrapy框架是如何管理Cookie的?# 默认启用了一个Cookie的中间件,实现了Cookie的自动化管理。将所有响应的Set-Cookie中的cookie信息保存下来,在后续的请求中,将这些cookie携带上。# 为什么单独添加Cookies?# 因为每一次请求列表页,都会返回一个新的Set-Cookie: vjkl5=,但是scrapy请求时自动携带的cookie,可能还是之前的旧的vjkl5=,就会导致这个POST请求携带的Cookie无法和服务器保存的Cookie不一致。# 设置上cookies,就意味着每次请求都携带最新返回的vjkl5的值。yield scrapy.FormRequest(url=url,callback=self.case_links_detail,formdata=meta,cookies={'vjkl5': vjkl5})# 在使用cookie的时候,观察cookie的值的变化。def case_links_detail(self,response):print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')json_string = re.search(re.compile(r'\[(.*?)\]', re.S), response.text)# 设置js代码 的执行环境os.environ["EXECJS_RUNTIME"] = "PhantomJS"js_content = open('D:\python练习\wenshu\wenshu\docid.js', encoding='utf8').read()# js_obj = execjs.compile #(js_content)返回一个js对象,该对象包含了js运行的环境。# 再使用js对象调用call()函数。# call('getKey', vjkl5)   #参数1-要执行的js文件中对应的函数,参数2-给调用函数传递的参数。if json_string:# 将字符串中 '\' 都替换为空。# \是特殊字符,需要表达普通字符\,需要使用\进行转义。result = json_string.group(1).replace("\\", '').replace('&ldquo;', '(').replace('&rdquo;', ')')# result是一个字符串 "{'RunEval':''},{'裁判要旨':'', '文书ID':''},{'裁判要旨':'', '文书ID':''},{'裁判要旨':'', '文书ID':''}"# 获取RunEval的值,加密字符串。runEval = re.search(re.compile(r'"RunEval":"(.*?)","', re.S), result).group(1)print(runEval)# 获取文书的IDdoc_ids = re.findall(re.compile(r'"文书ID":"(.*?)","', re.S), result)print(doc_ids)# 构建js的执行对象 执行js文件中的decode函数runeval = execjs.compile(js_content).call('decode',runEval)# 正则筛选出被JSFUCK加密的获取变量值得代码js_key = '$hidescript='+re.findall(r'\$hidescript=(.*?)_="constructor"',runeval)[0]# 构建js执行对象ctx = execjs.compile('''function js_KEY(){return %s}''' % js_key)# 执行js代码 获取$hidescript的值ctx_key = ctx.call("js_KEY")print(ctx_key)#这里需要将"进行转义ctx_key = '"'+ctx_key.replace('._KEY=','._KEY=\\')+'"'# 正则筛选出被JSFUCK加密的获取str_key函数的js代码,其中需要先获取到$hidescript的值js_str_key = re.findall(r'''_="constructor";_\[_\]\[_\](.*?)\(\);''',runeval)[0]# 将$hidescript替换成他的真实值js_str_key = js_str_key.replace('$hidescript',ctx_key)# 构建js执行对象str_key = execjs.compile('''function js_KEY(){return %s}''' % js_str_key)# 执行 js 获取str_keystr_key = str_key.call("js_KEY")print(str_key)real_str_key = re.findall(r'''_KEY="(.*?)";''',str_key)[0]print(real_str_key)for doc_id in doc_ids:# 构建js的执行对象 执行js文件中的Navi函数real_id = execjs.compile(js_content).call('Navi', doc_id, real_str_key)print(real_id)url = 'http://wenshu.court.gov.cn/content/content?DocID='+real_id+"&KeyWord="# yield scrapy.Request(url=url, callback=self.case_doc )def case_doc(self,response):print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**********************************')print(response.url)def get_metas(self,param,index,page,vl5x):'''  需要构造 POST 参数Param: 案件类型:刑事案件Index: 1Page: 10Order: 法院层级Direction: ascvl5x: 19df1bfbf20eb3ea82cba533number: wensguid: d39aa838-d6ad-2792bcbd-f975ac094318'''guid = self.get_guid()meta = {'Param': param,'Index': index,'Page': page,'Order': '法院层级','Direction': 'asc','vl5x': vl5x,'number': 'wens','guid': guid,}return metadef get_guid(self):guid = self.creat_guid() + self.creat_guid() + "-" + self.creat_guid() + "-" + self.creat_guid() + self.creat_guid() + "-" + self.creat_guid() + self.creat_guid() + self.creat_guid();return guiddef creat_guid(self):return execjs.eval('(((1 + Math.random()) * 65536) | 0).toString(16).substring(1)')

guid(self):
guid = self.creat_guid() + self.creat_guid() + “-” + self.creat_guid() + “-” + self.creat_guid() + self.creat_guid() + “-” + self.creat_guid() + self.creat_guid() + self.creat_guid();
return guid

def creat_guid(self):return execjs.eval('(((1 + Math.random()) * 65536) | 0).toString(16).substring(1)')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/56224.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

裁判文书解析思路

Param:关键词:利率,关键词:民间借贷Index:1Page:10Order:法院层级Direction:ascvl5x:a04d29b5c9bc4bcf5d988410number:YTAUguid:94940de9-cd1b-2f3fde45-14ef7a93a671 param是查询字符串&#xff0c;index是页码&#xff0c;page是一页展示的数据量&#xff0c;order是排序方式…

连载:阿里巴巴大数据实践—实时技术

阿里数据人都在用的内部技术经验 关注数智化转型俱乐部&#xff0c;数智化不迷路 摘要相对于离线批处理技术&#xff0c;流式实时处理技术作为一个非常重要的技术补充&#xff0c;在阿里巴巴集团内被广泛使用。 数据价值是具有时效性的&#xff0c;在一条数据产生的时候&#x…

阿里巴巴数学竞赛详细解答(据说晋级的直接P8岗)

关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 计算机视觉研究院专栏 作者&#xff1a;Edison_G 随着社会工作的沉淀&#xff0c;数学这些学问都忘记的差不多了&#xff0c;能力有限&#xff0c;解…

数学建模写作排版——LaTeX

笔记简介 2022年11月24日APAMCM开赛&#xff0c;但作为写论文的人员&#xff0c;在22号晚上11点对latex的使用还不是非常的熟练。于是在今天发奋图强&#xff0c;学会最基本的latex的用法。在有模板的情况下&#xff0c;能够写出完整的排版好看的文章。 latex模板 一般官网上…

项目组入职一个阿里的大 牛,看他写代码真的太优雅了

引言 很多同学在工作一段时间之后可能都有这样的困境&#xff0c;大家觉得自己总是在写业务代码&#xff0c;技术上感觉好像没有多大的长进&#xff0c;不知不觉就成为了CURD Boy或者Girl&#xff0c;自己想要去改变但是又不知道该从何处进行入手。 有的同学会去学习如何做架…

数学建模——论文(latex写作)

LaTeX 前言一、texlive 安装与Texstudio编辑器二、开始编辑基础编写文档1.设置文档类型:*宏包导入处&#xff1a; 2.开始正文 命令标题注释段落设置&#xff08;顶格与不顶格&#xff09; 图片表格公式行内公式行间公式行间公式之无编号行间公式之有编号 多行公式不带编号带编号…

他是阿里P11,靠写代码写成合伙人,身家几十亿,没有他,我们可能刷不了淘宝!...

点击“技术领导力”关注∆ 每天早上8:30推送 作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 他是阿里的“扫地僧”&#xff0c;写代码级别最高的人&#xff0c;一等一的技术高手&#xff0c;他非科班出身&#xff0c;用近20年的时间&#xff0c;修…

阿里巴巴数学大赛赛题公布,你敢来挑战吗?(含参考答案)

9月中旬&#xff0c;阿里巴巴在全球范围内发起一场数学比赛&#xff0c;旨在让全社会看到基础科学尤其是数学的价值&#xff0c;理解数学之美。目前&#xff0c;组织方正在紧张地阅卷中&#xff0c;AI会辅助阅卷。 这次数学大赛引发社会强烈关注。活动公开不到一周&#xff0c;…

大淘宝技术提出TTNet算法荣获“最佳工业论文奖”奖项

大淘宝技术商家赋能算法团队联合浙江大学提出的TTNet算法荣获“最佳工业论文奖”奖项。 由IEEE计算机学会、国际网络智能协会、美国计算机学会主办&#xff0c;牛津大学、昆士兰大学、迪肯大学、中国医学科学院、东南大学、南京财经大学、PIESAT、大淘宝技术部、IOS Press协办的…

今天,阿里巴巴报告厅里只谈快乐的数学

3月29日下午&#xff0c;伴随着巴赫的经典G大调小步舞曲&#xff0c;第一届阿里巴巴全球数学竞赛颁奖典礼在杭州举办。在阿里巴巴报告厅里&#xff0c;马老师为数十位年轻选手一一颁奖。这些来自全球各地的数学顶尖高手相聚一堂&#xff0c;谈论着快乐数学和数学之美。 马老师为…

【技术大牛招募】-- 阿里巴巴 南京研发中心

大家好&#xff0c;相信大家这段实际的的朋友圈都被阿里江苏总部的文章刷屏了&#xff0c;作为先遣部队&#xff0c;阿里巴巴集团客户体验事业群-智能创新中心-南京研发中心&#xff08;目前办公地点坐标江宁九龙湖&#xff09;&#xff0c;上图是同事拍的办公楼。现招募岗位如…

阿里巴巴人工智能实验室(Ali A.I. Labs)负责人浅雪近期问答整理

目前开发者平台成为大厂兵家必争之地。谷歌开发者平台&#xff0c;紧随其后百度的AI开发者平台&#xff0c;科大讯飞开放平台&#xff08;挑了一个1024大吉大利的日子发布&#xff09;。人工智能时代&#xff0c;连硬件厂商曙光都开始做开发者平台了&#xff08;10月24日&#…

连载:阿里巴巴大数据实践—数据开发平台

阿里数据人都在用的内部技术经验 关注数智化转型俱乐部&#xff0c;数智化不迷路 摘要介绍MaxCompute和阿里巴巴内部基于MaxCompute的大数据开发套件&#xff0c;并对在数据开发过程中经常遇到的问题和相关解决方案进行介绍。 数据只有被整合和计算&#xff0c;才能被用于洞察商…

语音聊天机器人

这个机器人有点智障&#xff0c;主要是免费的图灵机器人接口&#xff0c;就是前些日子没回家休假的雪轩的弟弟雪桐&#xff0c;一个微信聊天机器人&#xff0c;他可能没她姐姐功能多但还是可以使用的。 为什么写一个语音聊天机器人呢&#xff1f;还是上周六中午吃饭的时候&…

chatgpt赋能python:Python人脸对比技术介绍

Python人脸对比技术介绍 人脸识别技术在现代社会中得到了广泛的应用&#xff0c;具有便捷、高效和精度高等优点。Python作为一种高级编程语言&#xff0c;具有方便、易用的特点&#xff0c;受到了越来越多的人的青睐。Python人脸对比技术就是Python在人脸识别技术领域的一种重…

chatgpt赋能Python-python2下载安装教程

Python2下载安装教程 Python是一种高级编程语言&#xff0c;由于其易于学习和使用的特点&#xff0c;在全球范围内受到了广泛的欢迎和使用。Python2是Python语言的早期版本&#xff0c;虽然已经逐渐被Python3所取代&#xff0c;但仍有许多项目在使用Python2。因此&#xff0c;…

chatgpt赋能python:Python宏替换:让你的代码更高效

Python宏替换&#xff1a;让你的代码更高效 Python是一种高级编程语言&#xff0c;它将程序员从繁琐的底层实现细节中解放出来。Python宏替换是一种强大的编程技术&#xff0c;可以加速开发过程并提高代码的可读性。在本文中&#xff0c;我们将介绍Python宏替换&#xff0c;包…

类似于ChatGPT的优秀应用notion

notion 是一款流行的笔记应用。不过功能实际远超笔记&#xff0c;官方自己定义是&#xff1a;“将笔记、知识库和任务管理无缝整合的协作平台”。其独特的 block 概念&#xff0c;极大的扩展了笔记文档的作用&#xff0c;一个 block 可以是个数据库、多媒体、超链接、公式等等。…

陶哲轩的10岁与30岁

Terence Tao&#xff08;陶哲轩&#xff09;&#xff0c;1975年7月17日出生于澳大利亚Adelaide&#xff08;阿德莱德&#xff09;。本讲话作于1985年上半年&#xff0c;即陶哲轩尚未满10周岁时所作&#xff0c;一个稚气儿童&#xff0c;给大学生和教授们作报告&#xff0c;少见…