首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

Python爬虫入门教程 17-100 CSDN博客抓取数据

1.写在前面 写了一段时间的博客了,忽然间忘记了,其实博客频道的博客也是可以抓取的 其实这事情挺简单的,打开CSDN博客首页,他不是有个最新文章么,这个里面都是最新发布的文章。 打开F12抓取一下数据API,很容易就获取到了他的接口 提取链接长成这个样子 https://blog.csdn.net/api/articles?type=more&category=newarticles&shown_offset=1540381234000000 发现博客最新文章是一个瀑布流页面,不断下拉,只有一个参数shown_offset 在变化,按照我多年的行医经验,这个参数是个时间戳,而且肯定是上一次数据最后一条的时间戳。 基于这个理论,看一下数据,咦,猜对了~ 博客返回的数据看一下,是否对味 2.CSDN博客撸代码 这个步骤就非常简单了,就

优秀的个人博客,低调大师

《K8s监控神器——TSDB for Prometheus的入门与实践》

直播时间 2019年4月25日 19:00 - 19:40(30分钟分享+10分钟答疑) 主讲人 胡建洪(花名:莫趋)阿里云智能-数据库产品事业部技术专家 内容概要 Prometheus作为云原生监控的首选工具,其单机部署的架构设计在提供稳定性和易用性的同时,也使得数据存储受限于单节点的存储大小。阿里云TSDB针对这一痛点,为用户提供了易用性高,稳定性强,性价比优的存储技术方案。本次技术分享中,我们会展示如何配置阿里云TSDB作为Prometheus远程存储的流程,并量化展示本方案达到的查询吞吐高,延迟低,性能按需弹性扩展等优势。关注Prometheus的你,请千万不要错过本次技术分享。 直播地址 阿里数据库技术交流群扫码入群 观看直播

优秀的个人博客,低调大师

gitbook 入门教程之实用插件(新增3个插件)

插件没有什么逻辑顺序,大家可以按照目录大纲直接定位到感兴趣的插件部分阅读即可. 更多插件正在陆续更新中,敬请期待... 最新更新插件 tbfed-pagefooter 版权页脚插件 gitalk 评论插件 search-plus 中文搜索插件 gitalk 评论插件并不是 gitbook 插件,因而集成方式和一般的插件安装方式不同! tbfed-pagefooter 版权页脚插件 如果希望将网页源码暴露出去并接受公众的监督校准的话,使用edit-link插件可以直接链接到源码文件. 链接地址: https://plugins.gitbook.com/plugin/tbfed-pagefooter 激活插件配置 在 book.json 中配置 tbfed-pagefooter 插件,详细说明请参考 tbfed-pagefooter 插件. 示例: { "plugins": ["tbfed-pagefooter"], "pluginsConfig": { "tbfed-pagefooter": { "copyright":"&copy snowdreams1006", "modify_label": "文件修订时间:", "modify_format": "YYYY-MM-DD HH:mm:ss" } } } 安装 tbfed-pagefooter 插件 示例: $ gitbook install 测试 tbfed-pagefooter 插件 启动本地服务后,每个页面的页脚处都会自动生成版权信息以及当前文件的最后更新时间. 功能慎用: 如果文档频繁更新适合生成最后更新时间,如果长时间不更新文档,岂不是最后更新时间还是几年前,给读者的感觉像是不再维护了一样! 示例: $ gitbook serve disqus 评论插件 discus 是一款集成评论的插件,可以为静态网站添加动态评论,让你的网站动起来! 遗憾的是,discus 插件只有 FQ 才能正常使用,暂时没找到其他较好的替代方案. 注册 disqus.com 账号 gitbook 集成 disqus 插件中最重要的配置项就是注册 disqus.com 网站唯一标识. 注册并绑定域名 如果没有注册账号请先注册,否则直接登录,当然也支持第三方账号登录(我使用的是谷歌账号). 人机验证时,选出符合条件的全部图形,直到没有新的图形为止,这一点和国内的静态图片验证是不同的! 选择安装 disqus 插件(I want to install Disqus on my site ),接下来会绑定集成网站的域名. 接下来设置网站的相关信息,其中网站名称(snodreams1006)是唯一标示,接下来集成到 gitbook 用的就是这个简短名称,而分类和语言按照实际情况选择即可. 选择服务类型 disqus 网站提供的服务类型,有基础班(basic),加强版(plus),专业版(pro)和免费版(free). 每个版本计划有不同的收费标准以及相应的服务,可以根据实际情况选择适合自己的服务类型. 接下来以免费版为例进行有关演示 安装并配置 disqus 到网站 估计是这些网站提供了默认的集成方式,这里并没看到 gitbook 相关的网站,因此选择最后一个自定义网站. 填写网站的基本信息,其中网站缩写名称仍然是 snowdreams1006,网址填写 https://snowdreams1006.github.io/ ,至于其他信息根据实际情况填写即可. 至此 disqus.com 网站配置完成,接下来我们配置 gitbook 集成 disqus 插件. 安装并配置 disqus 插件 上一步我们已经获取到唯一的标识: snowdreams1006 ,接下来可以继续配置 disqus 插件了. 链接地址: https://plugins.gitbook.com/plugin/disqus 激活插件配置 在 book.json 中配置 disqus 插件,根据实际情况修改成自己的缩写名称(shortName). 示例: { "plugins": ["disqus"], "pluginsConfig": { "disqus": { "shortName": "snowdreams1006" } } } 安装 disqus 插件 示例: $ gitbook install 测试 disqus 插件 示例: $ gitbook serve 正常情况下(FQ),disqus 插件已经成功集成到 gitbook 网站了,因此推送到实际服务器上时看到的效果是这样的. 如果你不具备条件(FQ),那么你看到的仍然是这样的. gitalk 评论插件 本篇文章发表在开源中国后得到网友 @八一菜刀 的评论,让我推荐了gitalk 评论插件,初始使用了一下,确实不错,因此在这里更新下. 上述 disqus 评论插件虽然比较好用,但是注册是在 disqus.com 官网,需要特殊手段才能访问,即便成功配置了国内一般也是访问不到的,因此功能相当鸡肋. gitalk 评论插件解决了这一痛点,利用 github 的开发者接口授权,将讨论区的 issue 变成评论区,和 github 结合的如此紧密,适合用源码托管到 github 这类情况. 先混个脸熟,看一下 gitalk 官网 是如何介绍自己的呢. 看着效果确实不错,并且评论区的内容直接作为 github 仓库的 issue,这么好的想法我咋没想到呢! 好了,现在让我们开始集成到我们自己的项目中,遇到新鲜事物,当然先要参考官网介绍了. 申请 GitHub Application 授权 登录 github 账号,点击 在线申请 授权应用. 看到这一步,想必读者已经有个大概印象了,gitalk 插件是利用 github 的开发者服务,进行授权进而调用 issue 相关接口从而显示评论功能. 这种由官网提供的开发者服务还是比较好的,至少感觉比手动模拟提交要靠谱些,更何况走的是 OAuth 授权模式. 比如第三方应用提供微信登录,走的也是 OAuth 协议,这里的第三方应用当然就是现在说的 Gitalk 插件,微信就是我们的 github . 新建应用,首页 url 和授权回调 url 填写相同的首页链接即可,其他情况自定义填写. 应用登记成功后会生成 token 令牌,clientId 和 clientSecret 需要重点保存下来,待会需要用到. 安装并集成到网站 在需要添加评论的页面,添加下述内容引入 gitalk 插件,其中参数来自我们上一步获取的 clientId 和 clientSecret . 默认应该添加到 .html 页面,当然也可以添加到 .md 页面,毕竟 markdown 语法也支持 html 标签. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css"> <script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script> <div id="gitalk-container"></div> var gitalk = new Gitalk({ "clientID": "clientId", "clientSecret": "clientSecret", "repo": "GitHub repo", "owner": "GitHub repo owner", "admin": ["GitHub repo admin"], "id": location.pathname, "distractionFreeMode": false }); gitalk.render("gitalk-container"); 稍微解释下参数的含义: "clientID" : [必选] GitHub Application Client ID "clientSecret" : [必选] GitHub Application Client Secret "repo" : [必选] GitHub repository "owner" : [必选] GitHub repository 所有者,可以是个人或者组织 "admin" : [必选] GitHub repository 的所有者和合作者 (对这个 repository有写权限的用户) "id" : [可选] 页面的唯一标识,默认值: location.href, 长度必须小于50,否则会报错! "distractionFreeMode": [可选] 类似 Facebook 评论框的全屏遮罩效果,默认值: false 上述配置只是最简配置,如果想要了解更多高级配置,请参考 官方文档 测试集成效果 按照上述安装步骤,将代码复制到首页(README.md)文件中,然后推送到 github ,体验下集成效果. 注意: 这里必须推送到服务器,因为申请应用时填写的域名是线上地址,因而本地测试是不会成功的,会报错,这一点和微信支付的回调地址类似. 示例: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css"> <script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script> <div id="gitalk-container"></div> var gitalk = new Gitalk({ "clientID": "3f62415a283d19cbd696", "clientSecret": "aed0e1db0620bf5d0e3a3f0225f801997ad74e58", "repo": "snowdreams1006.github.io", "owner": "snowdreams1006", "admin": ["snowdreams1006"], "id": location.pathname, "distractionFreeMode": false }); gitalk.render("gitalk-container"); 上述参数仅供参考,实际使用中请替换成自己的配置,不然你也没有我仓库的权限,肯定会报错的啊! 心心相念的 gitalk 评论区呢?是不是哪里配置错了,为啥没有出来? 别急,要淡定,看一下提示说"未找到的 Issue 进行评论,请联系 @snowdreams1006 初始化创建",既然如此,那我们就操作一下吧! 点击下方的按钮 使用 Github登录 ,会跳转到相应的仓库,然后按照提示确定. 再次返回首页,刷新一下看看发生什么神奇的事情了? 终于集成了评论功能,而且还支持 markdown 格式的评论呢! 进一步思考 确实不错,心中自然是欣喜万分,但别高兴太早了,因为你会发现其他页面并没有评论区,也很好理解,我们目前仅仅在首页(README.md) 集成了 gitalk 插件,也就是说使用 gitbook build 输出的 index.html 首页才支持评论区,其他页面没有插入上述代码,自然是没有评论区功能的啊! 那如果想要实现全网站的所有页面都集成评论区功能,应该怎么办呢? 百度搜索了一下,并没有找到优雅的解决方案,如果有人能够提供更好的解决方案,还望不吝赐教,在此谢过. 既然网上找不到优雅的解决方案,那寻求专业人士的帮助也是一种好办法,我去哪找 gitalk 的使用者呢? 聪明的你或许已经想到了,解铃还须系铃人,当然是向推荐给我插件的大牛提问了! 他确实提供了一种思路,以下是网友@八一菜刀原话: 文档里面我用的是tbfed-pagefooter插件,不过我是在本地使用gitbook install后重写了该插件的js,无非就是在js里面加一段Gitalk的调用代码,这样使用gitbook build命令的时候,所有的页面都会有Gitalk的评论调用 人家既然已经提供了思路,不太好意思继续麻烦人家要源码,既然如此,那就自己动手吧! tbfed-pagefooter 插件很熟悉,一般是用于注明版权以及文章的修订时间的,而且作用于每个页面,这一点就满足了集成 gitalk 相关代码的基本要求. 大体方向确定后,目前就是解决如何在 tbfed-pagefooter 插件构建的相关生命周期内顺便执行我们的代码? 正常当前项目安装 tbfed-pagefooter 插件后应该存放于 /node_modules/gitbook-plugin-tbfed-pagefooter 目录,大致看一下插件的项目结构. gitbook-plugin-tbfed-pagefooter ├── LICENSE ├── README.md ├── assets │ └── footer.css ├── index.js └── package.json 1 directory, 5 files $ 为了基本看懂项目文件作用,特意去看了下 gitbook 插件开发文档,目标锁定在 index.js . 截取重要片段,原来是电子书构建前动态增加了 html 片段啊,这就好办了! hooks: { 'page:before': function(page) { var _label = '最后更新时间: ', _format = 'YYYY-MM-DD', _copy = 'powered by snowdreams1006' if(this.options.pluginsConfig['tbfed-pagefooter']) { _label = this.options.pluginsConfig['tbfed-pagefooter']['modify_label'] || _label; _format = this.options.pluginsConfig['tbfed-pagefooter']['modify_format'] || _format; var _c = this.options.pluginsConfig['tbfed-pagefooter']['copyright']; _copy = _c ? _c + ' all right reserved,' + _copy : _copy; } var _copy = '<span class="copyright">'+_copy+'</span>' var str = ' \n\n<footer class="page-footer">' + _copy + '<span class="footer-modification">' + _label + '\n{{file.mtime | date("' + _format + '")}}\n</span></footer>' str += '\n\n<link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">'+ '\n\n<script src="https://unpkg.com/gitalk@latest/dist/gitalk.min.js"></script>'+ '\n\n<div id="gitalk-container"></div>'+ '\n\n<script src="https://snowdreams1006.github.io/gitalk-config.js"></script>'; page.content = page.content + str; return page; } }, 看懂基本原理后顺便修改了版权说明以及修订时间格式,然后追加了集成 gitalk 的相关代码. 这里为了方便修改 gitalk 配置,特意将相关配置项单独托管到 github 专门的 gitalk-config.js 文件. 至于配置文件的内容,并没什么特殊之处,还是顺便贴一下吧! var gitalk = new Gitalk({ "clientID": "3f62415a283d19cbd696", "clientSecret": "aed0e1db0620bf5d0e3a3f0225f801997ad74e58", "repo": "snowdreams1006.github.io", "owner": "snowdreams1006", "admin": ["snowdreams1006"], "id": window.location.pathname, "distractionFreeMode": false }); gitalk.render("gitalk-container"); 至此,之后再本地构建电子书时(gitbook build),gitbook-plugin-tbfed-pagefooter 自然会顺便帮我们运行集成 gitalk 的相关代码,这才是相对来说比较优雅的做法. 当然也不一定非要借助 gitbook-plugin-tbfed-pagefooter 插件帮忙,也可以借助别的插件进行集成,甚至自己写个更好的插件. 小结 gitalk 插件相对 disqus 插件来说,更符合基本国情,只不过默认的集成方式只能一个页面一个页面去集成,当数量比较多时,工作量不敢想象. 因此,通过 gitbook 插件开发的方式,在源码文件输出为目标文件时加入相关集成代码,相当于手写100条输出语句和循环写100条输出语句. 其实本质上并没有改变什么,仍然是集成到每个页面中,但是简化了人工操作的工作量就是效率的提升. 如果有更高效更优雅的集成方式,欢迎大家一起探讨. edit-link 编辑链接插件 如果希望将网页源码暴露出去并接受公众的监督校准的话,使用edit-link插件可以直接链接到源码文件. 链接地址: https://plugins.gitbook.com/plugin/edit-link 激活插件配置 在 book.json 中配置 edit-link 插件,详细说明请参考 edit-link 插件. 示例: { "plugins": ["edit-link"], "pluginsConfig": { "edit-link": { "base": "https://github.com/snowdreams1006/snowdreams1006.github.io/blob/master", "label": "编辑本页" } } } 安装 edit-link 插件 示例: $ gitbook install 测试 edit-link 插件 如果不能正常跳转到源码文件,多次试验后重新更改 edit-link.base 节点内容,重新 gitbook serve 即可正常跳转源码文件. 示例: $ gitbook serve github 插件 添加 github 图标链接,方便直接跳转到 github 指定仓库. 链接地址: https://plugins.gitbook.com/plugin/github 激活插件配置 在 book.json 中配置 github 插件,详细说明请参考 github 插件. 示例: { "plugins": ["github"], "pluginsConfig": { "github": { "url": "https://github.com/snowdreams1006/snowdreams1006.github.io" } } } 安装 github 插件 示例: $ gitbook install 测试 github 插件 示例: $ gitbook serve search-plus 中文搜索插件 默认的 search 搜索插件是不支持中文搜索的,而 search-plus 则功能更强大些,两者不能共存,需要禁用或移除 search 插件. 链接地址: https://plugins.gitbook.com/plugin/search-plus 激活插件配置 在 book.json 中配置 github 插件,详细说明请参考 github 插件. 示例: { "plugins": [ "-lunr", "-search", "search-plus" ] } 安装 search-plus 插件 示例: $ gitbook install 测试 search-plus 插件 测试是否能够进行中文搜索,如果不能,请确保已移除默认的 "lunr" 和 "search" 插件. 示例: $ gitbook serve

优秀的个人博客,低调大师

新手怎么入门云计算

云计算可以为用户提供众多的服务,大致包括三个层次的服务,分别是基础设施即服务、平台即服务和软件即服务。通过云计算技术,这些应用可以大大的方便我们的生活,我们可以随时随地把我们需要存储的信息传上云端而不需要考虑存储空间等问题,我们还可以随时随地的举行会议,而不需要受地域的限制,不需要麻烦的出差,会议便可以轻松地得到解决,这样省下了许多的时间和金钱。 在产业发展领域: 云计算加速了产业优化升级步伐,越来越多的企业通过大规模部署云计算在推动战略性变革,实现更精准的决策和更深入的协作方面获得企业核心竞争优势。借助互联网、云计算技术,实现多业态融合,成为产业结构调整升级新方向,极大的促进中小企业创新创业和全社会信息化水平提升。 对于中小型企业来说,人才和预算相对比较有限,通过云计算,这些企业可以通过云计算提供的租用模式来使用其他公司企业的先进技术。 对于大企业而言,其主要是用云计算来做基础架构服务。 在公共服务领域: 云计算提升了服务水平和管理效率。随着云计算和大数据技术在智慧城市建设、社区精细管理、疾病预防和治疗、食品药品安全监管、环境污染监测等领域的逐渐应用,社会管理效率、公共服务水平和人民幸福感将得到极大的提升。 在个人生活领域: 云计算使工作更加高效,生活更加快乐。随着云计算、大数据时代的到来,云办公、云笔记、云视频、云记帐等被广泛应用,可穿戴设备随时关注着我们的健康。基于大数据的反馈经济,让我们生活的更加便捷。 云计算的市场潜力和发展前景是巨大的,其中云计算扩展投资价值、混合云计算的出现、移动云服务和云安全等几个方面是备受关注的。 如今安全性问题成为了云计算发展的最大阻碍,如何保证用户敏感数据不被怀有恶意的人所利用和窃取是目前迫切需要解决的问题。 云计算要发展壮大需要众多用户的参与,这就带来了关于隐私的问题出现, 大数据学习扣qun: 74零零加4一3八yi很多用户担心自己的隐私会被其收集和利用。云计算发展壮大要走的路还很长,需要解决的问题也很多,除了以上提到的两个问题,还有网络传输问题和如何建立统一的技术标准等问题需要处理,只有把这些问题都一一解决了,我们才能说云计算真正的融入了我们的生活,并且能给我们带来前所未有的方便和用得舒适与安心。 学习云计算要学哪些课程呢? Linux云计算网络管理实战 Linux系统管理及服务配置实战 Linux Shell自动化运维编程实战 开源数据库SQL/NOSQL运维实战 大型网站高并发架构及自动化运维项目 网站安全渗透测试及性能调优项目实战 公有云运维技术项目实战 企业私有云架构及运维实战 Python自动化运维开发基础 Python自动化运维开发项目实战 云计算服务模型 1、Infrastructure-as-a-Service(IaaS,基础设施即服务)。也有Hardware-as-a-Service(硬件即服务)的说 法。硬件即服务从字面意思会更好理解。 在过去,要搭建一个服务器运行某些应用,比如一个web网站。企业需要为此购买硬件设施。但是通过IaaS,那么该企业就可以把硬件相关内容外包出去,由云计算服务提供商来负责。企业用户可以对这些硬件设 施进行租用以运行应用服务,并且还可以节省对硬件设施的维护成本,缩小场地使用。 这些硬件设施包含网络光纤,服务器,存储设备等。 2、Platform-as-a-Service(PaaS,平台即服务)。PaaS服务提供商提供各种开发和分发应用的解决方案。或 者理解成把一个软件开发平台提供给你使用。所以使用这种服务的一般都是开发人员。 PaaS像是在IaaS上集成了操作系统,服务器程序,数据库等。 3、Software-as-a-Service (SaaS,软件即服务)。软件是用户经常接触的一层,所以这一模型好理解些。 SaaS服务提供商把应用软件安装在自己的服务器上。客户可以通过自己的需求,向服务提供商购买所需的应用 软件服务,按时长付费。客户购买后,只要能上网,就可以通过浏览器等软件使用到云端上的应用。

优秀的个人博客,低调大师

hanlp汉语自然语言处理入门基础知识介绍

自然语言处理定义: 自然语言处理是一门计算机科学、人工智能以及语言学的交叉学科。虽然语言只是人工智能的一部分(人工智能还包括计算机视觉等),但它是非常独特的一部分。这个星球上有许多生物拥有超过人类的视觉系统,但只有人类才拥有这么高级的语言。 自然语言处理的目标是让计算机处理或说“理解”自然语言,以完成有意义的任务,比如订机票购物或QA等。完全理解和表达语言是极其困难的,完美的语言理解等效于实现人工智能。 自然语言处理涉及的几个层次: 作为输入一共有两个来源,语音与文本。所以第一级是语音识别和OCR或分词(事实上,跳过分词虽然理所当然地不能做句法分析,但字符级也可以直接做不少应用)。接下来是形态学,援引《统计自然语言处理》中的定义:形态学(morphology):形态学(又称“词汇形态学”或“词法”)是语言学的一个分支,研究词的内部结构,包括屈折变化和构词法两个部分。由于词具有语音特征、句法特征和语义特征,形态学处于音位学、句法学和语义学的结合部位,所以形态学是每个语言学家都要关注的一门学科。 Hanlp自然语言处理开发包: 从事大数据方面工作的人对自然语言处理必然都是不陌生的,在Github上用户量最多的开源汉语自然语言处理工具是HanLP。HanLP的初始版本是在2014年初开发的,3月份的时候开始在Github上开源。2015年的时候集成在了大快搜索的DKNLP中,目前大快已经把DKNLP技术成果已经开源,并且整体装如HanLP项目,HanLP的版本已经到了V1.50。 Hanlp自然语言处理技术优势: 支持中文分词(N-最短路分词、CRF分词、索引分词、用户自定义词调、词性标注),命名实体识别(中国人民、音译人民、日本人民,地名,实体机构名识别),关键词提取,自动摘要,短语提取,拼音转换,简繁转换,文本推荐,依存句法分析(MaxEnt依存句法分析、神经网络依存句法分析)。提供Lucene查件,兼容Solr和ElasticSearch。 Hanlp自然语言处理应用领域: Hanlp已经被广泛应用于Lucene、Solr、ElasticSearch、hadoop、android、Resin等平台,有大量开源作者开发各种查件与拓展,并且被包装或移植到Python、C#、R、JavaScript等语言上去。

优秀的个人博客,低调大师

[雪峰磁针石博客]python 3.7极速入门教程4函数

本文教程目录 4函数 菲波那契序列: >>> # Fibonacci series: ... # the sum of two elements defines the next ... a, b = 0, 1 >>> while b < 10: ... print(b) ... a, b = b, a+b ... 1 1 2 3 5 8 本例的新特性。 第一行和最后一行有多赋值:第一行变量a和b同时获得了新的值0和1。最后一行右边首先完成计算,右边的表达式从左到右计算。 条件(b < 10)为true时while循环执行。这里Python类似C ,任何非零整数都为true;0为 false。判断条件也可以是字符串或列表等序列;所有长度不为零的为true ,空序列为false。示例中的测试是一个简单的比较。标准比较操作符与C相同: <(小于), >(大于), ==(等于),<=(小于等于),>=(大于等于)和!=(不等于)。 循环体需要缩进:缩进是Python组织语句的方法。在命令行下,缩进行需要插入空格或者tab。建议使用文本编辑 或者IDE,一般都提供自动缩进。命令行输入复合语句时,必须用空行来标识结束(因为解释器没办法猜识别最后一行),注意同一级的语句需要缩进同样数量的空白。建议使用空格而不是tab缩进。 print语句输出表达式的值。字符串打印时没有引号,每两个项目之间有空格。 >>> i = 256*256 >>> print('The value of i is', i) The value of i is 65536 逗号结尾就可以避免输出换行: >>> a, b = 0, 1 >>> while b < 1000: ... print(b, end=',') ... a, b = b, a+b ... 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987, 定义函数 菲波那契数列的函数: >>> def fib(n): # write Fibonacci series up to n ... """Print a Fibonacci series up to n.""" ... a, b = 0, 1 ... while a < n: ... print(a, end=' ') ... a, b = b, a+b ... print() ... >>> # Now call the function we just defined: ... fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 关键字def引入函数定义,其后有函数名和包含在圆括号中的形式参数。函数体语句从下一行开始,必须缩进的。 函数体的第一行语句可以是可选的字符串文本,即文档字符串。有些工具通过docstrings 自动生成文档,或者让用户通过代码交互浏览;添加文档字符串是个很好的习惯。 函数执行时生成符号表用来存储局部变量。 确切地说,所有函数的变量赋值都存储在局部符号表。 变量查找的顺序,先局部,然后逐级向上,再到全局变量,最后内置名。全局变量可在局部直接引用,但不能直接赋值(除非用global声明),尽管他们可以被引用, 因为python在局部赋值会重新定义一个本地变量。 函数的实际参数在调用时引入局部符号表,也就是说是传值调用(值总是对象引用, 而不是该对象的值)。 函数定义会在当前符号表内引入函数名。 函数名的值为用户自定义函数的类型,这个值可以赋值给其他变量当做函数别名使用。 >>> fib <function fib at 10042ed0> >>> f = fib >>> f(100) 0 1 1 2 3 5 8 13 21 34 55 89 没有return语句的函数也会返回None。 解释器一般不会显示None,除非用print打印。 >>> fib <function fib at 10042ed0> >>> f = fib >>> f(100) 0 1 1 2 3 5 8 13 21 34 55 89 从函数中返回 >>> def fib2(n): # return Fibonacci series up to n ... """Return a list containing the Fibonacci series up to n.""" ... result = [] ... a, b = 0, 1 ... while a < n: ... result.append(a) # see below ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # call it >>> f100 # write the result [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] return语句从函数中返回值,不带表达式的return返回None。过程结束后也会返回 None 。 语句result.append(b)称为调用了列表的方法。方法是属于对象的函数,如obj.methodename,obj 是个对象(可能是一个表达式),methodname是对象的方法名。不同类型有不同的方法。不同类型可能有同名的方法。append()向链表尾部附加元素,等同于 result = result + [b] ,不过更有效。 调用turtle库的函数 代码: # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # 技术支持 钉钉群:21745728(可以加钉钉pythontesting邀请加入) # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-12 # bowtie.py # Draw a bowtie from turtle import * pensize(7) penup() goto(-200, -100) pendown() fillcolor("red") begin_fill() goto(-200, 100) goto(200, -100) goto(200, 100) goto(-200, -100) end_fill() exitonclick() 方法 功能 fgoto(x, y) 移到位置(x,y)。 pensize(width) 将笔绘制的线的粗细设置为width或返回当前值。 pencolor(color) 将笔颜色设置为color或返回当前值。 fillcolor(color) 将填充颜色设置为color或返回当前值。 color(color) 将笔和填充颜色设置为color或返回当前值。 begin_fill() 开始填充 end_fill() 结束填充 turtlesize(factor) 以factor拉伸。 showturtle() 开始显示。 hideturtle() 停止显示 自己写画圆的函数 代码: # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # 技术支持 钉钉群:21745728(可以加钉钉pythontesting邀请加入) # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-12 # bowtie.py # Draw a bowtie from turtle import * def circle_at(x, y, r): """Draw circle with center (x, y) radius r.""" penup() goto(x, y - r) pendown() setheading(0) circle(r) circle_at(-200, 0, 20) begin_fill() circle_at(0, 0, 100) end_fill() circle_at(200, 0, 20) hideturtle() exitonclick() 深入Python函数定义 python的函数参数有三种方式。 默认参数 最常用的方式是给参数指定默认值,调用时就可以少传参数: def ask_ok(prompt, retries=4, reminder='Please try again!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise ValueError('invalid user response') print(reminder) 调用方式: 只给出必选参数: ask_ok('Do you really want to quit?') 给出一个可选的参数: ask_ok('OK to overwrite the file?', 2) 给出所有的参数: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!') in关键字测定序列是否包含指定值。 默认值在函数定义时传入,如下所示: i = 5 def f(arg=i): print(arg) i = 6 f() 上例显示5。 注意: 默认值只赋值一次。当默认值是可变对象(比如列表、字典或者大多数类的实例)时结果会不同。实例: def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) # 执行结果: [1] [1, 2] [1, 2, 3] 规避方式: def f(a, L=None): if L is None: L = [] L.append(a) return L 关键字参数 关键字参数 的形式: keyword = value。 def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!") 有效调用: parrot(1000) # 1 positional argument parrot(voltage=1000) # 1 keyword argument parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments parrot('a million', 'bereft of life', 'jump') # 3 positional arguments parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword 无效调用 parrot() # 没有必选参数 parrot(voltage=5.0, 'dead') # 关键参数后面有非关键字参数 parrot(110, voltage=220) # 同一参数重复指定值 parrot(actor='John Cleese') # 不正确的关键字参数名 关键字参数在位置参数之后,多个关键字参数的顺序先后无关,一个参数只能指定一次值,报错实例: >>> def function(a): ... pass ... >>> function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: function() got multiple values for keyword argument 'a' 最后一个如果前有两个星号(比如name)接收一个字典,存储形式参数没有定义的参数名和值。类似的单个星号比如*name表示接受一个元组。 def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, "?") print("-- I'm sorry, we're all out of", kind) for arg in arguments: print(arg) print("-" * 40) for kw in keywords: print(kw, ":", keywords[kw]) 调用 cheeseshop("Limburger", "It's very runny, sir.", "It's really very, VERY runny, sir.", shopkeeper='Michael Palin', client="John Cleese", sketch="Cheese Shop Sketch") 执行: -- Do you have any Limburger ? -- I'm sorry, we're all out of Limburger It's very runny, sir. It's really very, VERY runny, sir. ---------------------------------------- client : John Cleese shopkeeper : Michael Palin sketch : Cheese Shop Sketch 注意参数顺序是随机的,可以使用sort排序。 任意参数列表 def write_multiple_items(file, separator, *args): file.write(separator.join(args)) 参数列表解包 把列表或元组拆分成多个并列的参数。 >>> range(3, 6) # normal call with separate arguments [3, 4, 5] >>> args = [3, 6] >>> range(*args) # call with arguments unpacked from a list [3, 4, 5] 同样的字典可以用两个星号解包: >>> def parrot(voltage, state='a stiff', action='voom'): ... print("-- This parrot wouldn't", action, end=' ') ... print("if you put", voltage, "volts through it.", end=' ') ... print("E's", state, "!") ... >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} >>> parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised ! Lambda表达式 lambda关键字可创建短小的匿名函数,函数体只有一行,创建时就可使用。比如求和:lambda a, b: a+b。通常不建议使用,不过在pandas等数据分析库广泛使用。 >>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43 除了返回表达式,lambda还可以用作函数参数。 >>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')] >>> pairs.sort(key=lambda pair: pair[1]) >>> pairs [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')](1) 文档字符串 文档字符串的内容和格式建议如下。 第一简短介绍对象的目的。不能描述对象名和类型等其他地方能找到的信息,首字母要大写。 如果文档字符串有多行,第二行为空行以分隔概述和其他描述。描述介绍调用约定、边界效应等。 Python解释器不会从多行文档字符串中去除缩进,要用工具来处理。约定如下:第一行后的第一个非空行决定了整个文档的缩进。实例: >>> def my_function(): ... """Do nothing, but document it. ... ... No, really, it doesn't do anything. ... """ ... pass ... >>> print(my_function.__doc__) Do nothing, but document it. No, really, it doesn't do anything. 绘制人脸 代码: # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # 技术支持 钉钉群:21745728(可以加钉钉pythontesting邀请加入) # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-12 from turtle import * def circle_at(x, y, r): """Draw circle with center (x, y) radius r.""" penup() goto(x, y - r) pendown() setheading(0) circle(r) def eye(x, y, radius): """Draw an eye centered at (x, y) of given radius.""" circle_at(x, y, radius) def face(x, y, width): """Draw face centered at (x, y) of given width.""" circle_at(x, y, width/2) eye(x - width/6, y + width/5, width/12) eye(x + width/6, y + width/5, width/12) def main(): face(0, 0, 100) face(-140, 160, 200) exitonclick() main() 递归 factorial.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-25 # factorial.py def factorial(n): """Return n! = 1*2*3*...*n.""" if n <= 1: return 1 return n * factorial(n - 1) def main(): for n in range(20): print(n, factorial(n)) print(factorial(2000)) main() 执行结果 $ python3 factorial.py 0 1 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 10 3628800 11 39916800 12 479001600 13 6227020800 14 87178291200 15 1307674368000 16 20922789888000 17 355687428096000 18 6402373705728000 19 121645100408832000 Traceback (most recent call last): File "factorial.py", line 19, in <module> main() File "factorial.py", line 17, in main print(factorial(2000)) File "factorial.py", line 12, in factorial return n * factorial(n - 1) File "factorial.py", line 12, in factorial return n * factorial(n - 1) File "factorial.py", line 12, in factorial return n * factorial(n - 1) [Previous line repeated 993 more times] File "factorial.py", line 10, in factorial if n <= 1: 参考资料 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 本文源码地址 习题 1,画出如下图形:

优秀的个人博客,低调大师

[雪峰磁针石博客]python 3.7极速入门教程5循环

本文教程目录 5循环 语法基础 for语句 Python的for语句针对序列(列表或字符串等)中的子项进行循环,按它们在序列中的顺序来进行迭代。 >>> # Measure some strings: ... words = ['cat', 'window', 'defenestrate'] >>> for w in words: ... print(w, len(w)) ... cat 3 window 6 defenestrate 12 在迭代过程中修改迭代序列不安全,可能导致部分元素重复两次,建议先拷贝: >>> for w in words[:]: # Loop over a slice copy of the entire list. ... if len(w) > 6: ... words.insert(0, w) ... >>> words ['defenestrate', 'cat', 'window', 'defenestrate'] range()函数 内置函数 range()生成等差数值序列: >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range(10) 生成了一个包含10个值的链表,但是不包含最右边的值。默认从0开始,也可以让range 从其他值开始,或者指定不同的增量值(甚至是负数,有时也称"步长"): >>> range(5, 10) [5, 6, 7, 8, 9] >>> range(0, 10, 3) [0, 3, 6, 9] >>> range(-10, -100, -30) [-10, -40, -70] >>> range(-10, -100, 30) [] 如果迭代时需要索引和值可结合使用range()和len(): >>> a = ['Mary', 'had', 'a', 'little', 'lamb'] >>> for i in range(len(a)): ... print(i, a[i]) ... 0 Mary 1 had 2 a 3 little 4 lamb 不过使用enumerate()更方便,参见后面的介绍。 break和continue语句及循环中的else子句 break语句和C中的类似,用于终止当前的for或while循环。 循环可能有else 子句;它在循环迭代完整个列表(对于 for)后或执行条件为false(对于 while)时执行,但循环break时不会执行。这点和try...else而不是if...else相近。请看查找素数的程序: >>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print(n, 'equals', x, '*', n//x) ... break ... else: ... # loop fell through without finding a factor ... print(n, 'is a prime number') ... 2 is a prime number 3 is a prime number 4 equals 2 * 2 5 is a prime number 6 equals 2 * 3 7 is a prime number 8 equals 2 * 4 9 equals 3 * 3 continue语句也是从C而来,它表示退出当次循环,继续执行下次迭代。通常可以用if...else替代,请看查找偶数的实例: >>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print(n, 'equals', x, '*', n//x) ... break ... else: ... # loop fell through without finding a factor ... print(n, 'is a prime number') ... 2 is a prime number 3 is a prime number 4 equals 2 * 2 5 is a prime number 6 equals 2 * 3 7 is a prime number 8 equals 2 * 4 9 equals 3 * 3 pass pass语句什么也不做。它语法上需要,但是实际什么也不做场合,也常用语以后预留以后扩展。例如: >>> while True: ... pass # Busy-wait for keyboard interrupt (Ctrl+C) ... >>> class MyEmptyClass: ... pass ... >>> def initlog(*args): ... pass # Remember to implement this! ... 循环技巧 在字典中循环时,关键字和对应的值可以使用 items() 方法同时获取: >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): ... print(k, v) ... gallahad the pure robin the brave 在序列中循环时 enumerate() 函数同时得到索引位置和对应值: >>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print(i, v) ... 0 tic 1 tac 2 toe 同时循环两个或更多的序列,可以使用 zip() 打包: >>> questions = ['name', 'quest', 'favorite color'] >>> answers = ['lancelot', 'the holy grail', 'blue'] >>> for q, a in zip(questions, answers): ... print('What is your {0}? It is {1}.'.format(q, a)) ... What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue. 需要逆向循环序列的话,调用 reversed() 函数即可: >>> for i in reversed(xrange(1, 10, 2)): ... print(i) ... 9 7 5 3 1 使用 sorted() 函数可排序序列,它不改动原序列,而是生成新的已排序的序列: >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> for f in sorted(set(basket)): ... print f ... apple banana orange pear 若要在循环时修改迭代的序列,建议先复制。 >>> import math >>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8] >>> filtered_data = [] >>> for value in raw_data: ... if not math.isnan(value): ... filtered_data.append(value) ... >>> filtered_data [56.2, 51.7, 55.3, 52.5, 47.8] 循环 代码: # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # 技术支持 钉钉群:21745728(可以加钉钉pythontesting邀请加入) # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-12 # bowtie.py # Draw a bowtie from turtle import * def polygon(n, length): """Draw n-sided polygon with given side length.""" for _ in range(n): forward(length) left(360/n) def main(): """Draw polygons with 3-9 sides.""" for n in range(3, 10): polygon(n, 80) exitonclick() main() 参考资料 讨论qq群144081101 591302926 567351477 钉钉免费群21745728 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 本文源码地址 条件循环while 代码: # -*- coding: utf-8 -*- # Author: xurongzhong#126.com wechat:pythontesting qq:37391319 # 技术支持 钉钉群:21745728(可以加钉钉pythontesting邀请加入) # qq群:144081101 591302926 567351477 # CreateDate: 2018-6-12 # spiral.py # Draw spiral shapes from turtle import * def spiral(firststep, angle, gap): """Move turtle on a spiral path.""" step = firststep while step > 0: forward(step) left(angle) step -= gap def main(): spiral(100, 71, 2) exitonclick() main()

优秀的个人博客,低调大师

Java入门系列-25-NIO(实现非阻塞网络通信)

还记得之前介绍NIO时对比传统IO的一大特点吗?就是NIO是非阻塞式的,这篇文章带大家来看一下非阻塞的网络操作。 补充:以数组的形式使用缓冲区 package testnio; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class TestBufferArray { public static void main(String[] args) throws IOException { RandomAccessFile raf1=new RandomAccessFile("D:/1.txt","rw"); //1.获取通道 FileChannel channel1=raf1.getChannel(); //2.创建缓冲区数组 ByteBuffer buf1=ByteBuffer.allocate(512); ByteBuffer buf2=ByteBuffer.allocate(512); ByteBuffer[] bufs= {buf1,buf2}; //3.将数据读入缓冲区数组 channel1.read(bufs); for (ByteBuffer byteBuffer : bufs) { byteBuffer.flip(); } System.out.println(new String(bufs[0].array(),0,bufs[0].limit())); System.out.println("-----------"); System.out.println(new String(bufs[1].array(),0,bufs[1].limit())); //写入缓冲区数组到通道中 RandomAccessFile raf2=new RandomAccessFile("D:/2.txt","rw"); FileChannel channel2=raf2.getChannel(); channel2.write(bufs); } } 使用NIO实现阻塞式网络通信 TCP协议的网络通信传统实现方式是通过套接字编程(Socket和ServerSocket),NIO实现TCP网络通信需要用到 Channel 接口的两个实现类:SocketChannel和ServerSocketChannel 使用NIO实现阻塞式网络通信 客户端 package com.jikedaquan.blockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class Client { public static void main(String[] args) { SocketChannel sChannel=null; FileChannel inChannel=null; try { //1、获取通道 sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1666)); //用于读取文件 inChannel = FileChannel.open(Paths.get("F:/a.jpg"), StandardOpenOption.READ); //2、分配指定大小的缓冲区 ByteBuffer buf=ByteBuffer.allocate(1024); //3、读取本地文件,发送到服务器端 while(inChannel.read(buf)!=-1) { buf.flip(); sChannel.write(buf); buf.clear(); } } catch (IOException e) { e.printStackTrace(); }finally { //关闭通道 if (inChannel!=null) { try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(sChannel!=null) { try { sChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } } new InetSocketAddress("127.0.0.1", 1666) 用于向客户端套接字通道(SocketChannel)绑定要连接地址和端口 服务端 package com.jikedaquan.blockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class Server { public static void main(String[] args) { ServerSocketChannel ssChannel=null; FileChannel outChannel=null; SocketChannel sChannel=null; try { //1、获取通道 ssChannel = ServerSocketChannel.open(); //用于保存文件的通道 outChannel = FileChannel.open(Paths.get("F:/b.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE); //2、绑定要监听的端口号 ssChannel.bind(new InetSocketAddress(1666)); //3、获取客户端连接的通道 sChannel = ssChannel.accept(); //4、分配指定大小的缓冲区 ByteBuffer buf=ByteBuffer.allocate(1024); //5、接收客户端的数据,并保存到本地 while(sChannel.read(buf)!=-1) { buf.flip(); outChannel.write(buf); buf.clear(); } } catch (IOException e) { e.printStackTrace(); }finally { //6、关闭通道 if(sChannel!=null) { try { sChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(outChannel!=null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(ssChannel!=null) { try { ssChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 服务端套接字仅绑定要监听的端口即可 ssChannel.bind(new InetSocketAddress(1666)); 上面的代码使用NIO实现的网络通信,可能有同学会问,没有看到阻塞效果啊,确实是阻塞式的看不到效果,因为客户端发送一次数据就结束了,服务端也是接收一次数据就结束了。那如果服务端接收完成数据后,再向客户端反馈呢? 能够看到阻塞效果的网络通信 客户端 package com.jikedaquan.blockingnio2; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class Client { public static void main(String[] args) { SocketChannel sChannel=null; FileChannel inChannel=null; try { sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1666)); inChannel = FileChannel.open(Paths.get("F:/a.jpg"), StandardOpenOption.READ); ByteBuffer buf=ByteBuffer.allocate(1024); while(inChannel.read(buf)!=-1) { buf.flip(); sChannel.write(buf); buf.clear(); } //sChannel.shutdownOutput();//去掉注释掉将不会阻塞 //接收服务器端的反馈 int len=0; while((len=sChannel.read(buf))!=-1) { buf.flip(); System.out.println(new String(buf.array(),0,len)); buf.clear(); } } catch (IOException e) { e.printStackTrace(); }finally { if(inChannel!=null) { try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(sChannel!=null) { try { sChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 服务端 package com.jikedaquan.blockingnio2; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class Server { public static void main(String[] args) { ServerSocketChannel ssChannel=null; FileChannel outChannel=null; SocketChannel sChannel=null; try { ssChannel = ServerSocketChannel.open(); outChannel = FileChannel.open(Paths.get("F:/a.jpg"),StandardOpenOption.WRITE,StandardOpenOption.CREATE); ssChannel.bind(new InetSocketAddress(1666)); sChannel = ssChannel.accept(); ByteBuffer buf=ByteBuffer.allocate(1024); while(sChannel.read(buf)!=-1) { buf.flip(); outChannel.write(buf); buf.clear(); } //发送反馈给客户端 buf.put("服务端接收数据成功".getBytes()); buf.flip(); sChannel.write(buf); } catch (IOException e) { e.printStackTrace(); }finally { if(sChannel!=null) { try { sChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(outChannel!=null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(ssChannel!=null) { try { ssChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 服务端将向客户端发送两次数据 选择器(Selector) 想要实现非阻塞的IO,必须要先弄懂选择器。Selector 抽象类,可通过调用此类的 open 方法创建选择器,该方法将使用系统的默认选择器提供者创建新的选择器。 将通道设置为非阻塞之后,需要将通道注册到选择器中,注册的同时需要指定一个选择键的类型 (SelectionKey)。 选择键(SelectionKey)可以认为是一种标记,标记通道的类型和状态。 SelectionKey的静态字段: OP_ACCEPT:用于套接字接受操作的操作集位OP_CONNECT:用于套接字连接操作的操作集位OP_READ:用于读取操作的操作集位OP_WRITE:用于写入操作的操作集位 用于检测通道状态的方法: 方法名称 说明 isAcceptable() 测试此键的通道是否已准备好接受新的套接字连接 isConnectable() 测试此键的通道是否已完成其套接字连接操作 isReadable() 测试此键的通道是否已准备好进行读取 isWritable() 测试此键的通道是否已准备好进行写入 将通道注册到选择器: ssChannel.register(selector, SelectionKey.OP_ACCEPT); IO操作准备就绪的通道大于0,轮询选择器 while(selector.select()>0) { //获取选择键,根据不同的状态做不同的操作 } 实现非阻塞式TCP协议网络通信 非阻塞模式:channel.configureBlocking(false); 客户端 package com.jikedaquan.nonblockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Date; import java.util.Scanner; public class Client { public static void main(String[] args) { SocketChannel sChannel=null; try { //1、获取通道 sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",1666)); //2、切换非阻塞模式 sChannel.configureBlocking(false); //3、分配指定大小的缓冲区 ByteBuffer buf=ByteBuffer.allocate(1024); //4、发送数据给服务端 Scanner scanner=new Scanner(System.in); //循环从控制台录入数据发送给服务端 while(scanner.hasNext()) { String str=scanner.next(); buf.put((new Date().toString()+"\n"+str).getBytes()); buf.flip(); sChannel.write(buf); buf.clear(); } } catch (IOException e) { e.printStackTrace(); }finally { //5、关闭通道 if(sChannel!=null) { try { sChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 服务端 package com.jikedaquan.nonblockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; public class Server { public static void main(String[] args) throws IOException { //1、获取通道 ServerSocketChannel ssChannel=ServerSocketChannel.open(); //2、切换非阻塞模式 ssChannel.configureBlocking(false); //3、绑定监听的端口号 ssChannel.bind(new InetSocketAddress(1666)); //4、获取选择器 Selector selector=Selector.open(); //5、将通道注册到选择器上,并指定“监听接收事件” ssChannel.register(selector, SelectionKey.OP_ACCEPT); //6、轮询式的获取选择器上已经 “准备就绪”的事件 while(selector.select()>0) { //7、获取当前选择器中所有注册的“选择键(已就绪的监听事件)” Iterator<SelectionKey> it=selector.selectedKeys().iterator(); while(it.hasNext()) { //8、获取准备就绪的事件 SelectionKey sk=it.next(); //9、判断具体是什么事件准备就绪 if(sk.isAcceptable()) { //10、若“接收就绪”,获取客户端连接 SocketChannel sChannel=ssChannel.accept(); //11、切换非阻塞模式 sChannel.configureBlocking(false); //12、将该通道注册到选择器上 sChannel.register(selector, SelectionKey.OP_READ); }else if(sk.isReadable()) { //13、获取当前选择器上“读就绪”状态的通道 SocketChannel sChannel=(SocketChannel)sk.channel(); //14、读取数据 ByteBuffer buf=ByteBuffer.allocate(1024); int len=0; while((len=sChannel.read(buf))>0) { buf.flip(); System.out.println(new String(buf.array(),0,len)); buf.clear(); } } //15、取消选择键 SelectionKey it.remove(); } } } } 服务端接收客户端的操作需要在判断 isAcceptable() 方法内将就绪的套接字通道以读操作注册到 选择器中 在判断 isReadable() 内从通道中获取数据 实现非阻塞式UDP协议网络通信 发送端 package com.jikedaquan.nonblockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.util.Scanner; public class TestDatagramSend { public static void main(String[] args) throws IOException { //获取通道 DatagramChannel dChannel=DatagramChannel.open(); //非阻塞 dChannel.configureBlocking(false); ByteBuffer buf=ByteBuffer.allocate(1024); Scanner scanner=new Scanner(System.in); while(scanner.hasNext()) { String str=scanner.next(); buf.put(str.getBytes()); buf.flip(); //发送数据到目标地址和端口 dChannel.send(buf,new InetSocketAddress("127.0.0.1", 1666)); buf.clear(); } dChannel.close(); } } 接收端 package com.jikedaquan.nonblockingnio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Iterator; public class TestDatagramReceive { public static void main(String[] args) throws IOException { //获取通道 DatagramChannel dChannel=DatagramChannel.open(); dChannel.configureBlocking(false); //绑定监听端口 dChannel.bind(new InetSocketAddress(1666)); //获取选择器 Selector selector=Selector.open(); //读操作注册通道 dChannel.register(selector, SelectionKey.OP_READ); while(selector.select()>0) { Iterator<SelectionKey> it=selector.selectedKeys().iterator(); //迭代选择键 while(it.hasNext()) { SelectionKey sk=it.next(); //通道可读 if(sk.isReadable()) { ByteBuffer buf=ByteBuffer.allocate(1024); //接收数据存入缓冲区 dChannel.receive(buf); buf.flip(); System.out.println(new String(buf.array(),0,buf.limit())); buf.clear(); } } it.remove(); } } }

优秀的个人博客,低调大师

零基础入门学习Python爬虫必备的知识点!

关于Python有一句名言:不要重复造轮子。 但是问题有三个: 1、你不知道已经有哪些轮子已经造好了,哪个适合你用。有名有姓的的著名轮子就400多个,更别说没名没姓自己在制造中的轮子。 2、确实没重复造轮子,但是在重复制造汽车。包括好多大神写的好几百行代码,为的是解决一个Excel本身就有的成熟功能。 3、很多人是用来抓图,数据,抓点图片、视频、天气预报自娱自乐一下,然后呢?抓到大数据以后做什么用呢?比如某某啤酒卖的快,然后呢?比如某某电影票房多,然后呢? 在学习python中有任何困难不懂的可以加入我的python交流学习q u n:227-435-450,多多交流问题,互帮互助,里有不错的学习教程和开发工具。学习python有任何问题(学习方法,学习效率,如何就业),可以随时来咨询我。 我认为用Python应该能分析出来,这个现实的世界属于政治家,商业精英,艺术家,农民,而绝对不会属于Python程序员,纵使代码再精彩也没什么用。 以下是经过Python3.6.4调试通过的代码,与大家分享: 抓取知乎图片 听两个聊天机器人互相聊天(图灵、青云、小i) AI分析唐诗的作者是李白还是杜 彩票随机生成35选7 自动写检讨书 屏幕录相机 制作Gif动图 1、抓取知乎图片,只用30行代码: import re from selenium import webdriver import time import urllib.request driver = webdriver.Chrome() driver.maximize_window() driver.get("https://www.zhihu.com/question/29134042") i = 0 while i < 10: driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) try: driver.find_element_by_css_selector('button.QuestionMainAction').click() print("page" + str(i)) time.sleep(1) except: break result_raw = driver.page_source content_list = re.findall("img src="(.+?)" ", str(result_raw)) n = 0 while n < len(content_list): i = time.time() local = (r"%s.jpg" % (i)) urllib.request.urlretrieve(content_list[n], local) print("编号:" + str(i)) n = n + 1 2、没事闲的时候,听两个聊天机器人互相聊天: from time import sleep import requests s = input("请主人输入话题:") while True: resp = requests.post("http://www.tuling123.com/openapi/api",data={"key":"4fede3c4384846b9a7d0456a5e1e2943", "info": s, }) resp = resp.json() sleep(1) print('小鱼:', resp['text']) s = resp['text'] resp = requests.get("http://api.qingyunke.com/api.php", {'key': 'free', 'appid': 0, 'msg': s}) resp.encoding = 'utf8' resp = resp.json() sleep(1) print('菲菲:', resp['content']) 网上还有一个据说智商比较高的小i机器人,用爬虫的功能来实现一下: import urllib.request import re while True: x = input("主人:") x = urllib.parse.quote(x) link = urllib.request.urlopen( "http://nlp.xiaoi.com/robot/webrobot?&callback=__webrobot_processMsg&data=%7B%22sessionId%22%3A%22ff725c236e5245a3ac825b2dd88a7501%22%2C%22robotId%22%3A%22webbot%22%2C%22userId%22%3A%227cd29df3450745fbbdcf1a462e6c58e6%22%2C%22body%22%3A%7B%22content%22%3A%22" + x + "%22%7D%2C%22type%22%3A%22txt%22%7D") html_doc = link.read().decode() reply_list = re.findall(r'"content":"(.+?)\r\n"', html_doc) print("小i:" + reply_list[-1]) 3、分析唐诗的作者是李白还是杜甫: import jieba from nltk.classify import NaiveBayesClassifier # 需要提前把李白的诗收集一下,放在libai.txt文本中。 text1 = open(r"libai.txt", "rb").read() list1 = jieba.cut(text1) result1 = " ".join(list1) # 需要提前把杜甫的诗收集一下,放在dufu.txt文本中。 text2 = open(r"dufu.txt", "rb").read() list2 = jieba.cut(text2) result2 = " ".join(list2) # 数据准备 libai = result1 dufu = result2 # 特征提取 def word_feats(words): return dict([(word, True) for word in words]) libai_features = [(word_feats(lb), 'lb') for lb in libai] dufu_features = [(word_feats(df), 'df') for df in dufu] train_set = libai_features + dufu_features # 训练决策 classifier = NaiveBayesClassifier.train(train_set) # 分析测试 sentence = input("请输入一句你喜欢的诗:") print(" ") seg_list = jieba.cut(sentence) result1 = " ".join(seg_list) words = result1.split(" ") # 统计结果 lb = 0 df = 0 for word in words: classResult = classifier.classify(word_feats(word)) if classResult == 'lb': lb = lb + 1 if classResult == 'df': df = df + 1 # 呈现比例 x = float(str(float(lb) / len(words))) y = float(str(float(df) / len(words))) print('李白的可能性:%.2f%%' % (x * 100)) print('杜甫的可能性:%.2f%%' % (y * 100)) 4、彩票随机生成35选7: import random temp = [i + 1 for i in range(35)] random.shuffle(temp) i = 0 list = [] while i < 7: list.append(temp[i]) i = i + 1 list.sort() print('[0;31;;1m') print(*list[0:6], end="") print('[0;34;;1m', end=" ") print(list[-1]) 5、自动写检讨书: import random import xlrd ExcelFile = xlrd.open_workbook(r'test.xlsx') sheet = ExcelFile.sheet_by_name('Sheet1') i = [] x = input("请输入具体事件:") y = int(input("老师要求的字数:")) while len(str(i)) < y * 1.2: s = random.randint(1, 60) rows = sheet.row_values(s) i.append(*rows) print(" "*8+"检讨书"+" "+"老师:") print("我不应该" + str(x)+",", *i) print("再次请老师原谅!") 以下是样稿: 请输入具体事件:抽烟 老师要求的字数:200 检讨书 老师: 我不应该抽烟, 学校一开学就三令五申,一再强调校规校纪,提醒学生不要违反校规,可我却没有把学校和老师的话放在心上,没有重视老师说的话,没有重视学校颁布的重要事项,当成了耳旁风,这些都是不应该的。 同时也真诚地希望老师能继续关心和支持我,并却对我的问题酌情处理。 无论在学习还是在别的方面我都会用校规来严格要求自己,我会把握这次机会。 但事实证明,仅仅是热情投入、刻苦努力、钻研学业是不够的,还要有清醒的政治头脑、大局意识和纪律观念,否则就会在学习上迷失方向,使国家和学校受损失。 再次请老师原谅! 6、屏幕录相机,抓屏软件: from time import sleep from PIL import ImageGrab m = int(input("请输入想抓屏几分钟:")) m = m * 60 n = 1 while n < m: sleep(0.02) im = ImageGrab.grab() local = (r"%s.jpg" % (n)) im.save(local, 'jpeg') n = n + 1 7、制作Gif动图: from PIL import Image im = Image.open("1.jpg") images = [] images.append(Image.open('2.jpg')) images.append(Image.open('3.jpg')) im.save('gif.gif', save_all=True, append_images=images, loop=1, duration=1, comment=b"aaabb")

优秀的个人博客,低调大师

Golang 入门系列(二)学习Go语言需要注意的坑

上一章节我们已经了解了 Go 环境的配置,不了解的,请查看前面的文章 https://www.cnblogs.com/zhangweizhong/p/9459945.html,本章节我们将学习 Go 语言的基础语法中需要注意的点。 GO语言基础语法 go 的基础语法,我这里就不细说了,大家可以查看这个文章,学习Go 详细的语法:http://www.runoob.com/go/go-basic-syntax.html 最好是对照上面的例子,一个一个敲出来,这样效果最好。 下面是一个Go 程序的基本结构,包含(包声明,引入包,函数等) package main // 定义包名,package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。 import "fmt" // 导入需要使用的包(的函数,或其他元素) func main() { // 程序的入口函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数。 fmt.Println("Hello, World!") } GO语言注意的坑 不管学啥,刚开始都会遇到各种各样的坑。下面就来总结下学习go语言的过程中,遇到的各种坑。 1. 写C# 的人都会将“{” 独立一行,但是这在go 里面是错误的 “{” 必须更方法体 在同一行。我第一次写go 的就犯了这个错误,还不知道错误在哪。 func main() { fmt.Println("Hello, World!") } 2.if…else 语句中的 else 必须和 if 的 ’ } ’ 在同一行,否则编译错误 var a int = 30 if a < 20 { fmt.Print("a<20") } else { fmt.Print("a>=20") } 2. 包名的定义。你必须在源文件中非注释的第一行声明包名,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。 package main 3.在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。 如果你打算将多个语句写在同一行,则必须使用 ; 人为区分,但在实际开发中我们并不鼓励这种做法。 fmt.Println("Hello, World!") fmt.Println("www.fpeach.com") 3.main()函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数。然而,每个package 中,只能有一个main() 函数,否则会报main redeclared in this block previous declaration at .. 的错误。 package main import "fmt" func main() { /* 这是我的第一个简单的程序 */ fmt.Println("Hello, World!") } 4. 当函数、结构等标识符以一个大写字母开头,如:GetInfo,那么使用这种形式的标识符的对象就可以被外部包的代码所使用,这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。 // 公有函数,可以被外部包的代码所使用func Test() { . . . }// 私有函数,包的内部是可见、func test2() { . . . } 5. 标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。 以下是无效的标识符: 1ab(以数字开头) case(Go 语言的关键字) a+b(运算符是不允许的) 6. 错误 no new variables on left side of := ,意思是,“左边一个新的变量也没有!” func main() { var b int = 20 b := 30 fmt.Print(b) } 解决办法就是:对于x,y:=....这种形式,只要把其中的一个变量命名成新的就可以了。 7.不能使用++自增或- -自减运算符初始化变量和对变量赋值 package main import "fmt" func main(){ var a int = 10 var b int = a++ var c int = 20 c = a++ fmt.Print(a, b, c) } 作者:章为忠 出处:http://www.fpeach.com/ 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以微信:18618243664联系我,非常感谢。 扫下面的二维码关注我的微信公众号。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册