精华内容
下载资源
问答
  • 需求文档

    千次阅读 多人点赞 2019-03-29 18:10:18
    虽然用例软件研发和技术工作中应用的非常广泛,但是互联网产品规划和设计中,并不经常使用,互联网产品的需求表达为了敏捷效率,通常采用原型产品需求文档。 UML是英文Unified Modeling Language的缩写,中文...

    产品设计是一个由抽象的概念到具体形象化的处理过程,通过文字或图像等方式将我们规划的产品需求展现出来。它将产品的某种目的或需求转换为一个具体的物理或工具的过程,把一种计划、规划设想、问题解决的方法,通过具体的操作,以理想的形式表达出来。

    由于产品设计阶段要全面确定整个产品策略、外观、结构、功能,从而确定整个产品系统的布局,因而,产品设计的意义重大,具有“牵一发而动全局”的重要意义。如果一个产品的设计缺乏具体形象的表述,那么研发时就将耗费大量资源和劳动力来调整需求。相反,好的产品设计,不仅表现在功能上的优越性,而且便于执行时理解,从而使产品的研发效率得以增强。

    1、产品需求文档介绍

    产品设计的最终表述的形式被称为产品需求文档,业界常常称呼为PRD文档,这是英文Product Requirement Document的缩写。产品需求文档是将产品规划和设计的需求具体形象化表述出来的一种展现形式,主要用于产品界面设计和研发使用。

    PRD文档是基于BRD、MRD的延续文档,主要是一份给执行层面的工作人员阅读的文档,这部分人群绝大多数是设计与技术人员。在这类人群中,设计师更多依赖于产品原型进行交互或视觉的设计,因此看这份文档的人主要是技术人员。相对于技术人员,他们不太关注产品的商业需求和市场愿景,因为在进行产品讨论立项时,产品的定义就已经向参与设计和研发的人员宣讲过,因此技术人员更多的是关注界面、功能、交互、元素等等内容,因此产品需求文档是一份详细的产品功能需求说明文档,是产品文档中最底层和最细致的文档。

    因为阅读人类的因素,所以产品需求文档是一份没有闲话,直入主题的功能说明文档。并且产品需求文档是没有标准规范的,也没有统一的模板,每个公司都不一样和每个人也不一样,这个取决于个人习惯和团队要求。虽然产品需求文档没有明确的规范,但是目的都是一样的,必须能够明确产品的功能需求,便执行人员理解任务要求。

    2、产品需求文档写作

    产品需求文档是产品经过规划和设计之后的最终执行文档,因此这份文档的质量好坏直接影响到执行部门是否能够明确产品的功能和性能。

    2.1、罗列信息(信息结构图)

    在写产品需求文档之前,我们需要先罗列出产品功能的信息内容,这一步是将想法逐渐清晰的第一步,也是帮助我们接下来设计功能的辅助信息,同时也可以辅助服务端技术人员创建数据库。因为这是第一步,所以我们不需要罗列的很详细,在之后的步骤里,我们会逐步改进和完善信息内容。

    罗列信息内容的方式有很多种,文本形式、思维导图形式等等都可以,最主要的是能够清晰易懂,我最常用的方法就是使用思维导图软件(MindManager)罗列成结构图,因此我称这一步为“信息结构图”。

    shu-17

    上图是一张以Blog系统为示例的信息结构图。信息结构图是一种接近数据库结构的图表,在罗列信息结构时,更多的是考虑信息数据,但是他并不是真正意义的数据库结构。信息结构图是提供给产品经理自己梳理信息内容的结构图,也是方便产品经理和服务端技术人员沟通数据结构的参考图,技术人员会根据这张图表的内容再结合产品原型或需求文档,然后规划和设计出真正意义上的数据库结构。

    信息结构图中关于友情链接功能的信息数据只有“名称”和“链接”两个内容,但是在实际功能需求中,友情链接还有两个功能,分别是“显示或隐藏”和“是否新窗口打开”,这两个功能会在产品原型和需求文档中详细描述,但是在信息结构中是没有体现的,因为从产品层面上来说,这两个只是功能,并不是信息内容。但是在真正数据库中,友情链接的这两个功能分别也是有字段参数的,程序在读取该参数后便知道友情链接的属性,然后处理友情链接是显示还是隐藏,是新窗口打开还是本窗口打开。通过友情链接这个例子,我们就知道了在实际中数据结构和信息结构是不一样的,信息结构只是产品层面的数据内容。

    无论是什么样的产品类型,无论从哪里入手,我们第一步都是先要罗列信息结构,因为信息结构图不仅是辅助技术人员创建数据库的图表,也是辅助产品人员进行产品功能规划的参考,只有对信息或数据的结构了解了,我们才能更好的设计产品。

    信息结构图是我们将概念想法形成结构化的第一步,也是我们接下来几步工作的辅助文档,同时在接下来的几步工作中,我们还会不断的完善信息的结构。

    2.2、梳理需求(产品结构图)

    当我们对产品的信息结构了解后,我们就需要规整脑海中的产品需求,让想法更加结构化,因此这一步就要梳理产品的需求。在设计产品原型之前,我们首先要罗列出产品的功能结构,包括频道、页面、模块及元素。这一步依然使用思维导图软件,像绘制楼盘鸟瞰图一样将产品的结构绘制成结构图,因此我称这一步为“产品结构图”。

    产品结构图是一种将产品原型以结构化的方式展现的图表,结构内容也如同产品原型一样,从频道到页面,再细化页面功能模块和元素。所以产品结构图是产品经理在设计原型之前的一种思路梳理的方式,并不是给其他工作人员查看的文档,通过类似鸟瞰式的结构图可以让产品经理对产品结构一目了然,也方便思考。

    shu-18 shu-19

    如上图示例,“活动大全”的产品结构依次是:产品 -> 频道 -> 页面 -> 页面元素 -> 操作 -> 元素。我们换一个角度观看示例,产品结构图实际上就是一种结构化的产品原型。这样做的目的就是梳理产品结构逻辑,让我们清楚的知道产品有几个频道,频道下面有没有子频道或者有多少个页面,这些页面里又有哪些功能模块,这些功能模块里又有哪些元素。

    shu-19

    上图以我们第一步的“信息结构图”为基础绘制的“产品结构图”,有了这份结构导图,我们可以对产品进行鸟瞰式考虑和完善,当有问题时,修改起来也比原型和文档方便很多。比如在后续规划中,我们发现文章的图片等附件上传后,管理不太方便,这时就可以在结构图中增加一个“附件管理”频道。如果我们使用产品结构图的方式,那么附件管理的功能增加和修改就会比原型工具更加便捷和效率。

    产品结构图的方法同样适用于移动互联网产品的设计,并且比起Web产品更加容易梳理产品结构。

    产品结构图是一种让产品经理通过思维导图的方式梳理思路的方法,通过这种方法可以明确产品有多少个频道、有多少个页面、页面有多少个功能模块、功能模块有多少个元素,逐步的将脑海里的想法明确梳理成结构。虽然这种方法能够明确产品的结构,但是这样的思维导图也就只有产品经理自己能够看懂,因为对于设计和技术人员这是一个抽象的表述方式,如果没有详细的讲解,是很难理解的。

    产品结构图是将产品原型具体化的一种方式,只是罗列了产品的频道页面和功能,但是没有详细的进行推演,关于细化方面是否符合产品逻辑,是否符合用户体验,这些都是没有深思过的,因此我们接下来就要进行原型设计,开始具体的考虑可行性。

    2.3、原型设计(界面线框图)

    当我们逐渐清晰了产品的需求后,并梳理了产品的各个频道及页面,那么这一步就要开始验证这些想法的具体界面表现和方案的可行性了。

    原型设计是帮助我们更细致的思考,并做各项需求的评估,同时也是将自己脑海里的想法进行输出的一种方式。通过原型设计后,我们就可以进行产品宣讲了,相比较于抽象的文字描述,原型则更加直观的展现产品的需求,设计和技术人员或者老板也能够更加直观的了解到产品意图。

    原型设计是将结构化的需求进行框架化,因此原型也被称为线框图,具体的表现手法有很多种,相关的辅助软件也有很多,例如:Axure RP、Balsamiq Mockups、UIDesigner等等。

    当到了原型设计这一步时,已经不仅仅是构思了,我们需要更加深入的了解每个页面上元素和这些元素的属性。例如按钮元素,我们就需要考虑这个按钮的功能,并且这个功能操作后带给后端和前端的反馈。例如注册会员按钮,用户操作后,第一步逻辑是验证用户输入的信息是否合法,不合法则给出前端反馈;合法则和后端通信验证是否已经存在同样信息,已经存在则给出前端反馈,不存在则进入下一步,注册成功;注册成功后的反馈是跳转页面,还是弹出层提示用户完善资料,这些都是需要更详情的考虑。当然这些更细致的思考是留在需求文档撰写时的,而此时我们需要做的就是把这些元素通过原型表现出来。

    原型设计的表现手法主要有三种:手绘原型、灰模原型、交互原型。从工作效率的角度考虑,我非常建议先通过手绘的形式快速在草纸上绘制出产品的原型,推演和讨论方案的可行性。当方案的可行性被验证之后,我们再根据个人习惯或团队要求,通过软件工具进行更深入的设计。

    ① 手绘原型

    因为原型也被称为线框图,因此手绘是最简单直接的方法,也是最快速的表现产品轮廓的手法。

    手绘原型

    手绘原型在初期验证想法时非常高效,也方便讨论和重构,同时也适合敏捷开发时快速出原型。

    ② 灰模原型

    灰模原型是由图形设计软件制作而成,最常用的软件是Photoshop和Fireworks,相对手绘原型,灰模更加清晰和整洁,也适用于正式场合的PPT形式宣讲。

    灰模原型
    phone

    灰模原型也可以称之为平面原型,所以如果不会使用图形软件也可以使用Axure RP设计,相比交互原型,灰模原型只是缺少交互效果,仅仅是将产品需求以线框结构的方式展示出来,让产品需求更加规整的直观展现。

    shu-23

    ③ 交互原型

    交互原型是使用原型设计软件完成的原型,常用软件是Axure RP,通常情况交互原型的设计要早于产品需求文档,是产品经理想法推演的重要一步。通过Axure RP之类的交互原型软件制作出来的产品原型,在功能需求和交互需求的表现上,几乎和正式产品是一致的,所以有时交互原型也被称为产品Demo版。

    通常情况下交互原型是产品经理与交互设计师共同讨论确定,然后由交互设计师制作,但是绝大多数的公司是没有交互设计师这个职位的,因此这类工作最终是由产品经理来负责的。

    以上三种方法并不是渐进的流程,而是三种原型设计的方法,具体取决于你的产品需求和团队要求。

    对于产品经理来说,原型设计是为了帮助我们细致的考虑方案,并论证方案的可行性,同时也是为了产品宣讲时让听众能够清晰直观的了解产品,避免抽象的语言描述导致听众理解困难和理解偏差。产品原型也是为了确保产品在执行过程中,是按产品经理最初设想的需求和期望完成的,因此产品经理的原型是没有很高的要求的,只要对方能够听懂看懂就可以了,所以使用手绘原型是最高效率的方法。

    2.4、用例模型(产品用例图)

    用例(Use Case)是一种描述产品需求的方法,使用用例的方法来描述产品需求的过程就是用例模型,用例模型是由用例图和每一个用例的详细描述文档所组成的。在技术和产品的工作领域里都有用例模型的技能知识。技术人员的用例主要是为了方便在多名技术人员协同工作,或者技术人员任务交接时,让参与者更好的理解代码的逻辑结构。产品人员的用例主要是为了方便技术研发和功能测试时,让参与者更好的理解功能的逻辑。

    用例起源和发展于软件时代的产品研发,后来被综合到UML规范之中,成为一种标准化的需求表述体系。虽然用例在软件研发和技术工作中应用的非常广泛,但是在互联网产品规划和设计中,并不经常使用,互联网产品的需求表达为了敏捷效率,通常采用原型加产品需求文档。

    UML是英文Unified Modeling Language的缩写,中文称为统一建模语言或标准建模语言,是用例模型的建模语言,常用工具是Microsoft Office Visio。产品用例是一种通过用户的使用场景来获取需求的方式,每个用例提供了一个或多个场景,该场景说明了产品是如何和最终用户或其它产品互动,也就是谁可以用产品做什么,从而获得一个明确的业务目标。

    ① 用例图

    用例图并不是画成了图形的用例。用例图包含一组用例,每一个用例用椭圆表示,放置在矩形框中;矩形框表示整个系统。矩形框外画如图所示的小人,表示参与者。参与者不一定是人,可以是其它产品、软件或硬件等等。某一参与者与某一用例用线连起来,表示该参与者和该用例有交互。

    shu-24

    许多人通过UML认识了用例,UML定义为展现用例的图形符号。UML并不是为描述用例定义书写格式的标准,因此许多人误认为这些图形符号就是用例本身;然而,图形符号只能给出最简单的一个或一组用例的概要。UML是用例图形符号最流行的标准,但是除了UML标准,用例也有其它的可选择的标准。

    ② 用例描述文档

    用例图只是在总体上大致描述了产品所能提供的各种服务,让我们对于产品的功能有一个总体的认识。除此之外,我们还需要描述每一个用例的详细信息,这些信息应该包含以下内容:

    shu-25

    用例名称:本用例的名称或者编号

    行为角色:参与或操作(执行)该用例的角色

    简要说明:简要的描述一下本用例的需求(作用和目的)

    前置条件:参与或操作(执行)本用例的前提条件,或者所处的状态

    后置条件:执行完毕后的结果或者状态

    用例描述文档基本上是用文本方式来表述的,为了更加清晰地描述用例,也可以选择使用状态图、流程图或序列图来辅助说明。只要有助于表达的简洁明了,就可以在用例中任意粘贴用户界面和流程的图形化显示方式,或是其它图形。如流程图有助于描述复杂的决策流程,状态转移图有助于描述与状态相关的系统行为,序列图适合于描述基于时间顺序的消息传递。

    在互联网产品和设计中,用例的使用越来越少,通常有了产品原型再加上功能流程图和功能说明文档就能够将产品需求详细的表述清楚,所以也没有必须撰写用例了。但是在大公司里,往往会追求产品流程的规范性,要求撰写用例,不过在敏捷开发的时候也会采用其它更有效率的方式,不一定非要撰写用例。

    前面几步我们将产品需求逐渐细化并且通过原型的方式将产品需求形象化的展现了出来,但是在产品功能的逻辑细节方面,原型就非常不直观了,所以用例是一个非常重要的描述需求过程的文档。

    但是由于用例文档以文字为主,并且格式复杂,不适用于高效率的产品需求表述,所以展现逻辑流程的“功能流程图”是一个简洁直观的可替代用例文档的方式。

    shu-26

    (请点击查看大图)

    如上图所示,功能流程图是一种使用图形的方式表示算法逻辑的图表,因为千言万语不如一张图,通过流程图将“优惠券”功能模块的逻辑和需求非常形象直观、一目了然的展现了出来。

    流程图的展现方式也不会产生“歧义性”,便于理解,逻辑出错时也非常容易发现,并且可以直接转化为程序需求描述文档。

    2.6、需求文档(PRD文档)

    前面的几个步骤是为了帮助我们梳理需求、验证可行性和明确细节,到了这一步的时候我们已经非常清晰的了解产品需求,此时撰写产品需求文档可以大大减少和避免了撰写文档时容易忽略的细节黑洞。

    产品需求文档是将产品规划和设计的需求具体形象化表述出来的一种展现形式,主要用于产品界面设计和研发使用。因为每个人的习惯和团队要求都是不一样的,所以产品需求文档没有统一的行业规范标准,无论以什么样的格式撰写产品需求文档,最终的目的都是让执行人员能够理解产品需求,根据需求完成产品。

    产品需求文档的表现形式有很多种,常见的有Word、图片和交互原型这三种形式,文档内容通常包含信息结构图、界面线框图、功能流程图、功能说明文档。虽然产品需求文档没有标准的规范,但是有两项是必不可少的,那就是文件标识和修改记录。文档在撰写过程中,我们可以自行不断的修改完善,但是如果正式发布或交给团队其他成员后,一旦有了修改,为了文档的同步,我们就需要标注出文档的修改内容,备注修改记录,这样可以方便大家查看和了解改动的内容。关于文件标识和修改记录,格式都大同小异。

    prd

    ① Word

    这是传统意义上的产品需求文档,主要有四个部分组成(具体根据产品要求进行划分),分别是:结构图、全局说明、频道功能、效果图。

    因为产品需求文档的阅读者主要是偏向于技术人员,因此文档的目的性非常明确,就是要描述产品的功能需求,所有产品需求文档没有关于市场方面的描述。为了保证需求的执行效率,建议大家尽量减少不必要的文字,在能够让阅读者看懂并且了解产品意图的情况下,文字越少越好。这主要是因为绝大多数人是没有足够耐心认真看完产品需求文档的,因此我们要尽量减化文档内容。

    ①-1、结构图:

    ①-1.1、信息结构图:主要是辅助服务端技术人员创建或调整数据结构的参考文件

    ①-1.2、产品结构图:主要是辅助设计和技术开发人员了解产品的全局结构。

    ①-2、全局说明:

    主要讲解产品的全局性功能的说明,例如网站产品的页面编码、用户角色,移动产品的缓存机制、下载机制,这类全局性功能的说明。这里我举一个移动产品的“状态维持与恢复”的例子。示例如下:

    状态的维持与恢复

    当用户退出产品时(误操作、Home键、锁屏、自动关机),产品需要维持用户操作前的状态,当用户返回产品时仍可以恢复到之前状态,并继续使用。

    维持状态包括流程操作、信息浏览、文本输入、文件下载。

    锁屏状态时,如果用户在产品中有下载任务时,仍然保持下载。

    ①-3、频道功能:

    以频道为单位,页面为子项,分别描述产品的频道、页面及页面模块元素的功能需求。示例如下:

    1、频道名:频道介绍及需求说明

    2、页面1:页面介绍及需求说明

    2.1、页面模块1:模块功能需求说明

    2.1.1、页面模块1-元素1:功能说明

    2.1.2、页面模块1-元素2:功能说明

    2.2、页面模块2:模块功能需求说明

    在撰写功能需求时,我们需要考虑用户的流程,例如一个“完成”按钮,我们需要描述他完成后,系统要不要给出反馈提示(反馈提示是什么样的形式反馈,内容显示成什么,有没有内容需要调取数据库),或者要不要跳转页面(跳转到哪个页面,这个页面是其他频道页面,还是这个功能的子页面,如果是子页面就需要再描述这个子页面的模块及元素内容)。

    ①-4、效果图:

    效果图是由设计师完成的产品图,和实际开发完成的产品保真度一致。

    这个示例是一个移动产品(iPad)需求文档,其中部分隐私内容已过滤隐藏,并且只保留了首页和地图找房频道的需求说明。由于工作环境没有交互设计师,所以Word文档中包含了部分交互说明。

    ② 图片

    图片形式的产品需求文档是基于效果图的说明文件,将传统Word形式的功能需求说明标注在效果图上,这种方式经常使用在移动互联网领域,实际上是图文形式的交互需求文件,只是在此基础上更深入的描述出功能需求。

    对于图片形式的产品需求文档,我们只需要另外再描述一下全局说明,其他频道页面的需求直接以图片形式展示,这种方式相对于Word文档的纯文字更加生动易读并且直观,因此有一些产品经理非常喜欢用这种方式代替Word形式的产品需求文档。

    picture_prd

    ③ 交互原型

    这里指的交互原型就是前面篇章讲到的原型设计,使用Axure PR之类的交互原型设计软件制作出来的产品原型非常真实和直观,并且原型软件还支持元素标注和导出Word文档,因此很多产品经理都喜欢使用Axure PR来代替Word完成产品需求文档。

    当我们通过Axure PR制作出产品原型后,实际上他已经是很完善的产品Demo了,因此我们只需要加上元素的标注,在标注中说明功能需求,这样导出的HTML文件相比Word文档更直观易懂,是非常高效的产品需求说明方式。

    shu-31

    无论你采用哪种方式撰写需求文档,最终的目的都是为了方便团队成员理解产品的意图,因此哪种方法能够避免细节黑洞,高效完成产品的设计和研发,那么这种方法就是最有效的方法


    展开全文
  • word2013论文中添加已有的封面

    万次阅读 2018-03-12 21:25:17
    文档2:论文所在文档步骤一:对文档一 封面也进行复制步骤二:进入文档2,正文第一个字前粘贴所复制的文档一(按原格式粘贴)步骤三:此时封面最后部分与论文开头连一起,粘贴文档的最后面点击 插入--分页可...

    以word2013为例现有两个文档:

    文档1:封面文档;文档2:论文所在文档

    步骤一:对文档一 封面也进行复制

    步骤二:进入文档2,在正文第一个字前粘贴所复制的文档一(按原格式粘贴)

    步骤三:此时封面最后部分与论文开头连在一起,在粘贴文档的最后面点击  插入--分页可解决

    步骤四:页眉处理:因为封面的页眉与论文正文的页眉要有不同的设置,这里请参考

    https://jingyan.baidu.com/article/e52e3615a7b68a40c60c51d8.html

    步骤五:此时还存在问题是粘贴过来的封面和原来文档1中的格式不同,解决办法如下:

    打开文档1 ,点击红圈所示处:


    出现下面窗口:


    分别查看  页边距、纸张、板式、文档网络四个选项的内容,

    再打开文档2:查看封面所在节,严格按照文档1中的上述4项内容的设置去修改我们文档2中的封面页,切记后面的应用本节,如下图。


    此过程本人已亲试可行,望对大家有用。



    展开全文
  • Python爬取百度文库付费文档(PDF)

    万次阅读 多人点赞 2019-12-05 15:03:59
    Python爬取百度文库付费文档(PDF)@TOC PS:本文为本人学习python的一个小分享,仅供学习和参考使用,不可做商业利益的盗取! 工具准备 Python3.x; Python库:selenium、requests; 爬取页面及爬取分析 ...

    Python爬取百度文库付费文档(PDF)@TOC
    PS:本文为本人学习python的一个小分享,仅供学习和参考使用,不可做商业利益的盗取!

    工具准备

    Python3.x;
    Python库:selenium、requests;

    爬取页面及爬取分析

    https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=50
    打开网址,鼠标置于第一页上,右键打开元素,可以看到图片来自于一个链接。
    鼠标置于第一页上,右键打开元素,可以看到图片来自于一个链接 我们打开这个链接。
    在这里插入图片描述可以很清楚的看到,这是一个图片的下载链接。所以我们需要爬取这个文档,有一个很清晰的思路就是把每一页的图片链接截取下来,然后再通过requests打开该链接来保存图片,最后将所有图片合成PDF即可。

    功能模块代码的实现

    实现图片链接的获取

    首先,先介绍下selenium库,Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。所以,你在人工操作浏览器时可以看到的东西,在selenium也可以看到。这里,我们就使用selenium来获取这个页面的源代码。

    from selenium import webdriver
    driver = webdriver.Firefox() #selenium支持火狐、谷歌等浏览器
    driver.get('https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=50')
    print(driver.page_source)
    

    我们先打印下源码看看。由于源码太长,我只贴出跟我们需要爬取内容相关的部分。

    <div class="bd" id="pageNo-1" data-page-no="1" data-mate-width="892.83" data-mate-height="1263" style="height:1011.4411478109px;" data-scale="0.70691211401425" data-render="1"><div class="reader-parent-a929d320eefdc8d376ee3224 reader-parent " style="position:relative;top:0;left:0;-moz-transform:scale(0.99);-moz-transform-origin:left top;"><div class="reader-wrapa929d320eefdc8d376ee3224" style="position:absolute;top:0;left:0;width:100%;height:100%;"><div class="reader-main-a929d320eefdc8d376ee3224" style="position:relative;top:0;left:0;width:100%;height:100%;"><div class="reader-pic-layer" style="z-index:1"><div class="ie-fix"><div class="reader-pic-item" style="background-image: url(https://wkbjcloudbos.bdimg.com/v1/docconvert4643//wk/caae51448eb3233830370d1963fa165e/0.png?responseCacheControl=max-age%3D3888000&amp;responseExpires=Sun%2C%2019%20Jan%202020%2014%3A13%3A06%20%2B0800&amp;authorization=bce-auth-v1%2Ffa1126e91489401fa7cc85045ce7179e%2F2019-12-05T06%3A13%3A06Z%2F3600%2Fhost%2Fc895ec975bc2d19dc54d3f80ffe35c865e469fdabcd3501ae7ad5af14af5896a&amp;x-bce-range=0-84983&amp;token=eyJ0eXAiOiJKSVQiLCJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiIsImV4cCI6MTU3NTUyOTk4NiwidXJpIjp0cnVlLCJwYXJhbXMiOlsicmVzcG9uc2VDYWNoZUNvbnRyb2wiLCJyZXNwb25zZUV4cGlyZXMiLCJ4LWJjZS1yYW5nZSJdfQ%3D%3D.15JLNbl07gJ1bGi0wBW6Jqm%2BPpuUyz7gJlsdIgf%2FdLc%3D.1575529986);background-position:0px 0px;width:812px;height:1179px;z-index:1360;left:73.7565px;top:86.32625000000002px;opacity:1;-moz-transform: scale(1.0685,1.0685);position:absolute;overflow:hidden;"></div></div></div></div></div></div></div>
    
    

    我们可以看到,该图片元素ID为“pageNo-1”,图片链接在style="background-image:中。通常我们爬取源码都是利用BeautifulSoup库与lxml配合解析的。但这里利用这两个库解析都打印的源码存在丢失现象,可能的原因是该源码编码中存在gb2312编码。我也尝试了不同的解析库,都不行。于是,这里我们可以另辟蹊径,将所有的网页源码存于一个字符串中,然后对字符串进行一系列的处理,得到我们需要的url连接。

    mystring = driver.page_source; #将源码赋值给一个字符串
    page = 'pageNo-1'
    idx1 = mystring.find('<div class="bd" id="' + page) #找出<div class="bd" id="pageNo-1的索引
    mystring = mystring[idx1:] #通过索引先将索引前面的所有字符串删除
    idx1 = mystring.find("https") #我们可以发现URL的链接都是已https开头的
    idx2 = mystring.find(");background-position") #URL的结尾后面都跟着“);background-position“
    mystring = mystring[idx1:idx2] #然后再根据这两个索引,截取URL连接。这里需要注意的是python前后缩影截取为左闭右开的区间,及[idx1:idx2)
    pringt(mystring)#输出处理后的字符串检查
    

    打印结果为:https://wkbjcloudbos.bdimg.com/v1/docconvert4643//wk/caae51448eb3233830370d1963fa165e/0.png?responseCacheControl=max-age%3D3888000&responseExpires=Sun%2C%2019%20Jan%202020%2014%3A13%3A06%20%2B0800&authorization=bce-auth-v1%2Ffa1126e91489401fa7cc85045ce7179e%2F2019-12-05T06%3A13%3A06Z%2F3600%2Fhost%2Fc895ec975bc2d19dc54d3f80ffe35c865e469fdabcd3501ae7ad5af14af5896a&x-bce-range=0-84983&token=eyJ0eXAiOiJKSVQiLCJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiIsImV4cCI6MTU3NTUyOTk4NiwidXJpIjp0cnVlLCJwYXJhbXMiOlsicmVzcG9uc2VDYWNoZUNvbnRyb2wiLCJyZXNwb25zZUV4cGlyZXMiLCJ4LWJjZS1yYW5nZSJdfQ%3D%3D.15JLNbl07gJ1bGi0wBW6Jqm%2BPpuUyz7gJlsdIgf%2FdLc%3D.1575529986
    我们打开这个链接,发现无法打开。回到我们手动打开的页面,复制一下正确的网址与之进行对比。
    正确的URL:https://wkbjcloudbos.bdimg.com/v1/docconvert4643//wk/caae51448eb3233830370d1963fa165e/0.png?responseCacheControl=max-age%3D3888000&responseExpires=Sun%2C%2019%20Jan%202020%2011%3A27%3A12%20%2B0800&authorization=bce-auth-v1%2Ffa1126e91489401fa7cc85045ce7179e%2F2019-12-05T03%3A27%3A12Z%2F3600%2Fhost%2Faf0214c3c956c28ad864419c09c58541d9f6d00fd7a73c92624fc7aa69b484ed&x-bce-range=123043-197963&token=eyJ0eXAiOiJKSVQiLCJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiIsImV4cCI6MTU3NTUyMDAzMiwidXJpIjp0cnVlLCJwYXJhbXMiOlsicmVzcG9uc2VDYWNoZUNvbnRyb2wiLCJyZXNwb25zZUV4cGlyZXMiLCJ4LWJjZS1yYW5nZSJdfQ%3D%3D.uGj%2F8Z9kAT4ldgOX62nSX2By9c7pOhNhA1g90oRH%2Bxg%3D.1575520032
    这里请忽略链接的不同,该图片链接本身就是动态链接,每次链接都不同,我们只需要关注格式。对比发现,我们打印的URL中多出了几个“amp;”
    https://wkbjcloudbos.bdimg.com/v1/docconvert4643//wk/caae51448eb3233830370d1963fa165e/0.png?responseCacheControl=max-age%3D3888000&amp;responseExpires=Sun%2C%2019%20Jan%202020%2014%3A13%3A06%20%2B0800&==amp;==authorization=bce-auth-v1%2Ffa1126e91489401fa7cc85045ce7179e%2F2019-12-05T06%3A13%3A06Z%2F3600%2Fhost%2Fc895ec975bc2d19dc54d3f80ffe35c865e469fdabcd3501ae7ad5af14af5896a&amp;x-bce-range=0-84983&amp;token=eyJ0eXAiOiJKSVQiLCJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiIsImV4cCI6MTU3NTUyOTk4NiwidXJpIjp0cnVlLCJwYXJhbXMiOlsicmVzcG9uc2VDYWNoZUNvbnRyb2wiLCJyZXNwb25zZUV4cGlyZXMiLCJ4LWJjZS1yYW5nZSJdfQ%3D%3D.15JLNbl07gJ1bGi0wBW6Jqm%2BPpuUyz7gJlsdIgf%2FdLc%3D.1575529986
    我们把“amp;”删除了试试。mystring = mystring.replace('amp;', '')
    再次打印后打开链接就可以发现,可以正常下载了。到此,图片链接获取功能实现。

    实现图片的下载

    图片的下载我们可以使用requests.content来实现。

    r = requests.get(mystring)
    with open(page + '.png', 'wb') as png:
    	png.write(r.content)
    png.close()
    

    运行后就可以看到一个pageNo-1.png图片的生成。打开看看,果然就是我们刚刚看到的第一页。

    实现浏览器下滑及按钮的点击

    上面两个模块只是实现的第一页的图片的下载。百度文库中,第三页都免会有一个打开更多页的按钮,我们需要点击该按钮才可以获得更多的页面。我们先通过浏览器获得该按钮元素的ID或者class name。

    <div id="html-reader-go-more" class="banner-wrap more-btn-banner" style="height: auto;">
    <div class="banner-core-wrap super-vip"><div class="doc-banner-text">下载文档到电脑,使用更方便</div>    <div class="doc-banner-value"><div><span class="icon-ticket"></span>5下载券</div><div class="doc-banner-ticket-rights">(您持有<span>0</span>下载券,积分不足无法兑换)</div></div><div class="doc-banner-btns super-vip">                <div class="btn-pay-vip"><i></i>VIP免费下载</div></div><div class="doc-banner-tip super-vip"><div class="doc-banner-rights-wrap"><span class="icon-triangle" style="left: 221.5px;"></span><div class="download-pro-doc"><i></i>享VIP专享文档下载特权</div><div class="download-share-doc"><i></i>赠共享文档下载特权</div><div class="yuedu-vip"><i></i>赠百度阅读VIP精品版</div></div></div></div>
    <div class="continue-to-read">
    <div class="banner-more-btn">
    <span class="moreBtn goBtn">
    <span>还剩63页未读,</span>
    <span class="fc2e">继续阅读</span>
    </span>
    <p class="down-arrow goBtn"></p>
    </div>
    <div class="hengxian"></div>
    </div>
    <div class="wubai-wrap">
    <div class="wubai-title">
    <span class="wubai-icon"></span>
    

    很直观的就可以看到,该按钮class=“down-arrow goBtn”。通过xpath来定位该按钮,再进行click的动作即可实现点击按钮。

    button = driver.find_element_by_xpath("//p[@class='down-arrow goBtn']")
    button.click()
    time.sleep(2) #请在头文件加入 import time,单位秒
    

    这里我引入了time库的sleep函数,是考虑到网速问题,让浏览器缓冲一下。
    按钮的点击实现了。我们还会发现一个问题,那就是有时候后面几页的图片无法加载,这里我的处理方式是,没爬取一个页面就讲滑条滑动到该页,同时缓冲2S保证图片的加载成功。很可惜selenium没有关于浏览器滑条的操作,这里需要配合JS进行滑条的操作。

    target = driver.find_element_by_id(page)#page={pageNo-1,pageNo-2,....}是图片的ID,上文有提到
    driver.execute_script("arguments[0].scrollIntoView();", target)#上一句是找到该元素,这一句是运用JS滑动滑条到该元素
    time.sleep(2)
    

    代码的集合

    上面那个章节将我们需要的功能都实现了(其实还有一个功能模块我没有弄,那就是图片合成PDF。但是我比较懒,而且现在WORD直接一键插入所有图片,然后输出成PDF比较方便,所以这里我就没弄,只是保存了所有的图片),最后我们只需要进行整合即可。
    此处该文档共有两个链接。
    1-50页链接为:https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=50
    50-66页链接为:https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=51
    所以爬取的时候记得更换链接。
    代码集合如下:

    from selenium import webdriver
    import time
    import requests
    
    driver = webdriver.Firefox()
    driver.get('https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=50')
    for i in range(50):
        if i == 3:
            target = driver.find_element_by_id('html-reader-go-more')
            driver.execute_script("arguments[0].scrollIntoView();", target)
            button = driver.find_element_by_xpath("//p[@class='down-arrow goBtn']")
            button.click()
            time.sleep(2)
        page = 'pageNo-' + str(i+1)
        print(page)
        target = driver.find_element_by_id(page)
        driver.execute_script("arguments[0].scrollIntoView();", target)
        time.sleep(2)
        mystring = driver.page_source;
        idx1 = mystring.find('<div class="bd" id="' + page)
        print(idx1)
        mystring = mystring[idx1:]
        idx1 = mystring.find("https")
        print(idx1)
        idx2 = mystring.find(");background-position")
        print(idx2)
        mystring = mystring[idx1:idx2]
        mystring = mystring.replace('amp;', '')
        if mystring.startswith('http') :
            r = requests.get(mystring)
            with open(page + '.png', 'wb') as png:
                png.write(r.content)
            png.close()
        else:
            print(mystring)
    
    driver.get('https://wenku.baidu.com/view/9a5a21cf964bcf84b9d57bea?pn=51')
    for i in range(50,66):
        page = 'pageNo-' + str(i + 1)
        print(page)
        target = driver.find_element_by_id(page)
        driver.execute_script("arguments[0].scrollIntoView();", target)
        time.sleep(2)
        mystring = driver.page_source;
        idx1 = mystring.find('<div class="bd" id="' + page)
        print(idx1)
        mystring = mystring[idx1:]
        idx1 = mystring.find("https")
        print(idx1)
        idx2 = mystring.find(");background-position")
        print(idx2)
        mystring = mystring[idx1:idx2]
        mystring = mystring.replace('amp;', '')
        if mystring.startswith('http'):
            r = requests.get(mystring)
            with open(page + '.png', 'wb') as png:
                png.write(r.content)
            png.close()
        else:
            print(mystring)
    driver.quit()
    

    总结

    1.selenium确实好用,运用好了可以做很多事情;
    2.BeautifulSoup与lxml无法解析网页时,多换种思路,也可以实现功能;
    3.新学python,若有错误,请大神们轻喷,也请指正,谢谢;
    4.本文仅供学习python的selenium库的学习参考,切勿用于商业利益,我们要尊重别人的知识产权。

    展开全文
  • Python学习心得之一近期刚上手学习Python,学习完一些基础教程后,开始动手做一些小项目。之后也会不定期更新一些学习心得……准备阶段本人的开发环境采用Python2.7+cmd命令窗口的形式,安装方法可以参考网上一些...

    Python学习心得之一

    近期刚上手学习Python,在学习完一些基础教程后,开始动手做一些小项目。之后也会不定期更新一些学习心得……


    准备阶段

    本人的开发环境采用Python2.7+cmd命令窗口的形式,安装方法可以参考网上一些教程。

    在开始之前参考阅读了一些资料和博客
    例如:
    如何用Python做中文词云?
    十分钟学会用任意中文文本生成词云
    python中文词云生成
    还有一些参考阅读的资料就不细举了

    操作阶段

    生成词云需要用到一些Python扩展包,最好采用命令窗口pip的方式下载,而在此之前,需要在网上下载pip安装好(此处网上也有参考教程)
    然后在命令行窗口敲击如下代码:

    pip install matplotlib

    下载完成后再依次下载wordcloud包和jieba包
    附jieba包下载成功图:

    下载成功图

    现在我们可以开始敲代码了

    首先是参考了这份资料的代码
    如何用Python做中文词云?

    前面运行的都还顺利,包括建立TXT文本,读取内容,进行中文分词
    但是运行到如下代码的时候出现了问题

    from wordcloud import WordCloud 
    wordcloud = WordCloud().generate(mytext) 
    %pylab inline 
    import matplotlib.pyplot as plt 
    plt.imshow(wordcloud, interpolation='bilinear' 
    plt.axis("off")

    此段代码里%pylab inline 运行出错了,错误如下:

    运行错误

    经过查找资料后发现,这段代码可能是只对IPython开发环境有效。于是便放弃了用这种方式显示词云。

    进而参考了第三份资料的词云设置代码:
    python中文词云生成

    和第二份资料的显示词云代码:
    十分钟学会用任意中文文本生成词云

    但是在词云设置代码中:

    wc = WordCloud( background_color = 'white',  # 设置背景颜色
                    mask = backgroud_Image,      # 设置背景图片
                    max_words = 2000,            # 设置最大现实的字数
                    stopwords = STOPWORDS,       # 设置停用词
                    font_path = 'C:/Users/Windows/fonts/simsun.ttf',     # 设置字体格式,如不设置显示不了中文
                    max_font_size = 60,          # 设置字体最大值
                    color_func=None,             #设置关键字的字体颜色
                    random_state = 42,           # 设置有多少种随机生成状态,即有多少种配色方案
                    ).generate(mytext)

    关于font_path的设置,需要保证该路径中含有中文字体,如果没有,需要在网上下载相关字体,放入此路径中。此处我们采用的是simsun.ttf宋体中文字体。

    在词云显示代码中含有两种不同的显示方法:

    plt.imshow(wc)  #第一种 直接按设置好的字体颜色 背景形状来显示
    image_colors = ImageColorGenerator(backgroud_Image)
    wc.recolor(color_func = image_colors)
    plt.imshow(wc)  #第二种 根据前两句代码 将字体颜色变成了背景图的颜色
    plt.axis('off')
    plt.show()

    实际上第二种显示方法使用较多,因为第一种颜色太过花花绿绿
    两种显示方法图片有如下区别:

    第一种:
    直接显示

    第二种:
    采用背景图颜色显示

    原背景图:
    原背景图

    出现的错误

    1、就是如上所述操作阶段的代码错误

    2、在代码无误后,第一种方法显示出来的图形没有按照设定背景图的形状来显示,而是变成了矩形的形状。

    在请教了同学@sunhuan之后,发现原来是我找的背景图的背景和图片颜色过于相近,导致机器识别不出来边缘形状,在更换相差度高的图片之后,顺利的显示出了相应形状的词云。

    至此,本次生成中文词云完成,附完整代码如下:

    完整代码

    import matplotlib.pyplot as plt
    #import pickle
    from wordcloud import WordCloud,STOPWORDS,ImageColorGenerator
    import jieba
    filename = "jade.txt"
    with open(filename) as f:
        mytext = f.read()
    mytext = " ".join(jieba.cut(mytext))         #进行中文分词
    backgroud_Image = plt.imread('D:\pycharm\projects\world.jpeg')
    wc = WordCloud( background_color = 'white',  # 设置背景颜色
                    mask = backgroud_Image,      # 设置背景图片
                    max_words = 2000,            # 设置最大现实的字数
                    stopwords = STOPWORDS,       # 设置停用词
                    font_path = 'C:/Users/Windows/fonts/simsun.ttf', # 设置字体格式,如不设置显示不了中文
                    max_font_size = 60,          # 设置字体最大值
                    color_func=None,             #设置关键字的字体颜色
                    random_state = 42,           # 设置有多少种随机生成状态,即有多少种配色方案
                    ).generate(mytext)
    plt.imshow(wc)
    image_colors = ImageColorGenerator(backgroud_Image)
    wc.recolor(color_func = image_colors)
    plt.imshow(wc)
    plt.axis('off')
    plt.show()
    展开全文
  • eclipse中加入API文档帮助

    千次阅读 2018-01-25 10:12:04
    首先,你的文档需要是HTML版的,如果没有的话,可以去下载,不想下载的话...这里你需要chm版的API文档,通过命令反编译chm文件, windows 下 ,方法如下: 命令行,输入hh -decompile 例如:hh -deco
  • Qt帮助文档使用方法

    千次阅读 2019-10-22 20:22:18
    Qt 帮助文档非常细致而全面,应有尽有,是非常不错的自学教材。因为 Qt 帮助文档太多,所以难以都翻译成中文,即使翻译了一部分,翻译花的时间太多,翻译更新的时效性也难以保证,所以还是得看英文帮助为主。本节...
  • 说明: 本文原创作者『strongerHuang』 ...一、写在前面 上一篇文章让你入门STM32CubeMX,你可能还是会觉得心里摸不到底。本文就从另外一个角度带你了解STM32CubeMX。 本文讲述STM32CubeMX各主...
  • html中前端页面预览pdf文档的6种方法

    千次阅读 2020-12-22 11:05:46
    html中前端页面预览pdf文档的6种方法 转载于https://www.jianshu.com/p/61065b749ff8
  • 2021年前端面试题及答案

    万次阅读 多人点赞 2020-02-11 19:29:34
    前端面试汇总(2020年) 一 大纲 1、前言 2、前端工程化 3、前端设计模式 4、前端安全性问题 ...由于新冠肺炎疫情,现在成天呆家里,加上也要准备面试,就家里看面试题...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    immortality按:请用ctrl+f中查找某一部分的内容或某一命令的用法。 -------------------------------------------------------------------------------- Linux必学的60个命令(1)-安装与登陆命令 login 1...
  •  2)点击第三的页眉页码,选项卡中选择《页眉和页脚》,会发现此时同前节是开启着的,这意味着第三的页眉页脚和第二是一样的   图二、《页眉和页脚》选项卡的同前节选项  3)点击一下同前节,把它...
  • 可以通过输入来选择已有的标签,也可以添加新标签,还可以取消已经设置的标签。 实际上,系统还会根据标签抽取算法,自动识别文档的标签,准确率还是非常高的哦 点击标签,就可以显示对应标签相关的资源。 ...
  • 需求文档(PRD文档)

    万次阅读 多人点赞 2018-03-05 22:11:21
    虽然用例软件研发和技术工作中应用的非常广泛,但是互联网产品规划和设计中,并不经常使用,互联网产品的需求表达为了敏捷效率,通常采用原型产品需求文档。 UML是英文Unified Modeling Language的缩写,中文...
  • PDF文档解密及数字签名技术(三)   读取加密的PDF文档   前文说过,加密的PDF文档,其中的字符串和流都是被加密的,要正确的解读这些信息,就要对其进行解密,解密就需要密钥,那么密钥怎么来呢?与加密...
  • 需求文档(PRD文档)应该怎么写?

    千次阅读 2019-05-13 19:43:10
    虽然用例软件研发和技术工作中应用的非常广泛,但是互联网产品规划和设计中,并不经常使用,互联网产品的需求表达为了敏捷效率,通常采用原型产品需求文档。 UML是英文Unified Modeling Language的缩写,...
  • 由于各个构件是逐渐并入已有的软件体系结构中的,所以加入构件必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构 开发过程中,需求的变化是不可避免的。增量模型的灵活性可以使其适应这种变化的...
  • MfC打开过程详解及应用...Open 对应的ID为ID_FILE_OPEN,其响应过程如下:注:如果自己将ID_FLIE_OPENMFC中重载了,则会直接响应重载函数,不会按以下过程响应。1.点击File-&gt;Open,首先响应的函数为: C...
  • 软件测试面试题汇总

    万次阅读 多人点赞 2018-09-27 12:31:09
    2、我现在个程序,发现Windows上运行得很慢,怎么判别是程序存在问题还是软硬件系统存在问题?   5 3、测试的策略哪些? ................................................................................
  • java爬虫

    千次阅读 多人点赞 2019-04-12 11:59:12
    这样的爬虫程序, 垂直爬虫 例如: 慢慢网, 笔趣阁 开发过程中, 大部分开发的都是垂直爬虫, 1.4 爬虫的基本原理 [外链图片转存失败,源站可能防盗链机制,建议将图片保存下来直接上传(img-s2DZvhH4-1605084008952)...
  • 56. 为所有公开的 API 元素编写文档注释 如果 API 要可用,就必须对其进行文档化。传统上,API 文档是手工生成的,保持文档与代码的同步是一件苦差事。Java 编程环境使用 Javadoc 实用程序简化了这一任务。Javadoc...
  • 使用apidocJs快速生成在线文档

    万次阅读 多人点赞 2017-03-18 10:40:00
    使用者仅需要按照要求书写相关注释,就可以生成可读性好、界面美观的在线接口文档。本文主要包含以下内容: 介绍apidoc的基本概念 安装、使用和简单配置 一些特殊参数的含义及其使用 介绍一些使用经验 前言apidoc能...
  • 最近使用项目组另一位同学发来的maven项目时,出现错误,检查许久未发现错误出现哪里,现在发现是因为末尾标签后存在空格,所以无法加载xml文件,记录,错误代码未保存,望见谅
  • 如何写出受技术欢迎的需求文档

    千次阅读 2018-10-31 14:49:01
    正如我们做出来的产品都希望受用户欢迎,开发和测试是需求文档的用户,产品经理也应该重视他们的想法和要求才能写得令人满意。 “写需求文档”说专业点是把用户(或运营、客服等)的需求转化成技术部门的话语,因此...
  • MyBatis官方文档-动态 SQL

    千次阅读 2019-09-16 14:49:04
    如果你使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种...
  • RocketMQ中文文档(译)

    万次阅读 多人点赞 2018-01-30 09:55:30
    前言:近日需要研究一下RocketMQ,为了方便日后查找,因此对官方英文文档进行翻译记载,也希望能帮助到要学习的朋友。阅读后发现,文档还是比较粗略的,大概也只能了解些概念和简单实用。快速入门部分比较简单,因此...
  • 微信小程序开发指南(新手必备)

    万次阅读 多人点赞 2019-05-23 16:44:37
    确保服务器公网网络正常,且指向公网IP的域名备案,状态正常 由于微信小程序API必要得备案域名才能访问,所以域名需要通过ICP备案(具体如何备案,这里不做说明) 1.2 端口可用 确保80和443端口开放,且...
  • XML文档类型定义---DTD文档

    千次阅读 2016-06-27 13:48:59
    XML中可以创建新的标记语言,这些新的标记语言(也叫标记集)要通过文档类型定义(Document Type Definitions,DTD)来定义。DTD文档是这些新的标记语言的法律性文档。如果XML文档的语法符,DTD的定义和规定,那么就...
  • 需求文档是典型的说明文,力求逻辑清楚、言简意赅。...(1)一些移动端产品不写文档,直接原型上备注,但遇到逻辑复杂的时候还是要写文档。 建议大家写文档,因为写的过程会发现更多。 (2)文档...
  • 在前面的示例中,您为所有域存储库定义了一个公共基本接口,并公开了findById(…)以及save(…)。这些方法被路由到Spring Data提供的所选商店的基本存储库实现中( 例如,如果您使用JPA,则实现是...
  • 使用Word的主控文档,是制作长文档最合适的方法。主控文档包含几个独立的子文档,可以用主控文档控制整篇文章或整本书,而把书的各个章节作为主控文档的子文档

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 255,747
精华内容 102,298
关键字:

如何在已有文档前面加页