关于python3.x:爬取搜狗微信文章

一、获取索引页。增加好headers,params间接get申请即可。二、在索引页中获取详情页的url。在浏览器中间接关上这个url,认真看浏览器上方中url,你会发现url会跳转,就是说他进行了重定向。这里咱们须要应用fiddler这个抓包工具对他进行抓包。你会发现他返回的是一段js代码,代码拼接成的url就是咱们想要的真正的real_url,这里咱们间接用正则表达式,进行匹配、拼接就ok了。三、获取详情页。既然获取到了详情页的实在url,剩下的结构一下申请头headers,间接申请即可,这里我不举荐加cookie参数到申请头里,因为加上之后拜访次数过多,他会封cookie,让你输出验证码进行验证。四、总结。我看网上说他是封ip,封cookie的,然而我爬了几百篇并没有发现这个状况,之后遇到再补充。附上代码: import requestsfrom lxml import etreeimport reimport urllib3# 重定向、封ip、封cookieurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)def get_index(start_url, page): params = { 'query': '美女', '_sug_type_': '', 'sut': '1828', 'lkt': '1,1597298703444,1597298703444', 's_from': 'input', '_sug_': 'y', 'type': '2', 'sst0': '1597298703546', 'page': page, 'ie': 'utf8', 'w': '01019900', 'dr': '1', } headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': 'ABTEST=5|1597380273|v1; SNUID=59BBCE9AEAEF4626F956F592EA96FE70; IPLOC=CN3709; SUID=B3512470160DA00A000000005F3616B1; JSESSIONID=aaapSleD9Qep4fAnwHYox; SUV=0004E05A702451B35F3616B1A47C7070; SUID=B35124706A13A00A000000005F3616B1', 'Host': 'weixin.sogou.com', 'Referer': 'https://weixin.sogou.com/weixin?query=%E7%BE%8E%E5%A5%B3&_sug_type_=&sut=1828&lkt=1%2C1597298703444%2C1597298703444&s_from=input&_sug_=y&type=2&sst0=1597298703546&page=4&ie=utf8&w=01019900&dr=1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36', } response = requests.get(url=start_url, params=params, headers=headers, verify=False) if response.status_code == 200: html = etree.HTML(response.text) urls = html.xpath('//ul[@class="news-list"]/li//h3/a/@href') for url in urls: url = 'https://weixin.sogou.com/' + url print(url) yield url else: print('getting index page fail')def get_real_url(url): headers = { 'Host': 'weixin.sogou.com', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Referer': 'https://weixin.sogou.com/weixin?type=2&s_from=input&query=%E7%BE%8E%E5%A5%B3&ie=utf8&_sug_=n&_sug_type_=', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'Cookie': 'SUID=D85024704A21A00A000000005EFDF58C; SUV=0035E9CD702450D85EFDF58D4E7EB415; weixinIndexVisited=1; LCLKINT=121; LSTMV=468%2C24; pgv_pvi=2192807936; ABTEST=0|1596950375|v1; IPLOC=CN3709; SNUID=C32054007175DCCBC54D7C1071164832; JSESSIONID=aaaMv1RDeodhj5yAwCYox; PHPSESSID=34n87c5popss5ckq1gcinpc9s2', } response = requests.get(url=url, headers=headers, verify=False) pattern = re.compile('\+=.*?\'(.*?)\';', re.S) url_list = re.findall(pattern, response.text) real_url = '' for i in url_list: real_url += i real_url.replace('@', '') return real_urldef get_detail(url): headers = { 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'cache-control': 'max-age=0', 'if-modified-since': 'Fri, 14 Aug 2020 12:33:50 +0800', 'sec-fetch-dest': 'document', 'sec-fetch-mode': 'navigate', 'sec-fetch-site': 'cross-site', 'sec-fetch-user': '?1', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36', } response = requests.get(url, headers=headers,verify=False) html = etree.HTML(response.text) if html.xpath('//*[@id="activity-name"]/text()'): title = html.xpath('//*[@id="activity-name"]/text()')[0].strip() else: title = '' result = { 'title': title, } return resultif __name__ == '__main__': start_url = 'https://weixin.sogou.com/weixin' for page in range(1, 11): urls = get_index(start_url=start_url, page=page) for url in urls: real_url = get_real_url(url) result = get_detail(real_url) print(result)

August 14, 2020 · 2 min · jiezi

关于python3.x:python-解析htmlscript标签内变量内容

最近在试用scrapy爬取网站数据发现局部图表是通过异步生成的,scrapy获取到的html页面内只有一个空标签。因而只能查找其原数据,还好通过翻查实例化表格的js文件就追溯到了。然而数据在原html页面内的script标签内以js间接定义,如下图:不能间接通过xpath获取,而且是一般object和array两种格局,通过间接字符串操作必定不够优雅。因而须要绕一下: import js2xmlimport jsonimport xmltodictfrom lxml.etree import tostringimport xmldict_simplify #下文定义的办法#中略...dataName ="forecast_1h"scripts = response.xpath('//script/text()').extract()#获取特定script标签的内容,不蕴含标签自身script =list(filter(lambda x: (dataName in x ),scripts))[0]#script内容 → xmlxml = js2xml.parse(script,encoding='utf-8',debug=False)如果这一步间接xml转json的话,会失去这样的数据即带数据类型的json数据,然而这样的dict天然是不好用的,因而定义个办法解决下 def typeParse(xmlobj): keys = list(xmlobj.keys()) if(len(keys)>1): #援用类型嵌套调用 if(keys[1]=="array"): return {xmlobj[keys[0]]:list(map(lambda x:typeParse(x),xmlobj["array"]["object"]))} elif(keys[1]=="object"): return {xmlobj[keys[0]]:typeParse(xmlobj["object"])} if(len(keys)==1 and keys[0]=="property"): _property = {} for item in xmlobj["property"]: _keys = list(item.keys()) #值类型间接输入 if(_keys[1]=="string"): _property[item["@name"]] = item["string"] elif(_keys[1]=="number"): _property[item["@name"]] = item["number"]["@value"] #援用类型持续解决 else: _property[item["@name"]] = int(typeParse(item)[item["@name"]]) return _property在主流程内应用 ...

August 12, 2020 · 1 min · jiezi

python3-调用-ansible-模块和-fastapi-实现项目监控接口-实例

问题说明1.pm2 通过 json 文件 启动node service时,当同时开启多实例(instances)集群和 --inspect 断点 websocket 端口将无法指定2.而且项目可能在不同环境部署在不同的系统中 3.开发同学权限不足无法查看pid从而找到websocket 端口 { "apps": { "args": [ "debug", "3121" ], "cwd": "/data/source/service-sk_platform_professional_rda/publish/", "error_file": "/data/pm2-log/errlogs/service-sk_platform_professional_rda-err.log", "exec_interpreter": "node", "exec_mode": "fork", "instances": "4", "log_date_format": "YYYY-MM-DD HH:mm Z", "max_memory_restart": "8100M", "max_restarts": "50", "merge_logs": true, "min_uptime": "20s", "name": "service-sk_platform_professional_rda", "node_args": "--inspect=0.0.0.0:33121 --max-old-space-size=8000", "out_file": "/data/pm2-log/outlogs/service-sk_platform_professional_rda-out.log", "pid_file": "/data/pm2-log/outlogs/service-sk_platform_professional_rda.pid", "script": "/data/source/service-sk_platform_professional_rda/publish/service/server.js", "watch": false }}python3 安装ansible 模块pip3 install ansiblepip3 install ansible_runner pip3 install ansible_inventory pip3 install ansible_playbook ...

July 8, 2020 · 5 min · jiezi

爬取今日头条街拍图片

参考于崔庆才的Python爬虫教程,但是崔的视频时间过长,今日头条网站反爬虫也有了变化,因此写下此文章来记录自己的爬取过程遇到的问题,也给大家一些借鉴。欢迎大家讨论。一、获取街索引页。我们会发现doc下服务器给出的response里面全是些js代码,没有我们想要的二级页面链接。然后查看XHR下,preview会发现我们要的数据全在这里面,他是以一个json对象的存放的,由此我们知道他是由Ajax渲染的。(一般下滑加载出数据的基本都是ajax动态渲染的)。再看他的请求字符参数、请求头参数有很多,不过没什么问题,直接复制过来即可。 def get_index(offset, keyword): para = { 'aid': '24', 'app_name': 'web_search', 'offset': offset, 'format': 'json', 'keyword': keyword, 'autoload': 'true', 'count': '20', 'en_qc': '1', 'cur_tab': '1', 'from': 'search_tab', 'pd': 'synthesis', 'timestamp': '1593665684775', '_signature': '7' + 'yD7.AAgEBApd0Jxcjcfwe8huuAALHovmaBcff719uWpg6PhnCCgTgbuUckg1kLI3dQFdQZ1b3VwbtvV9P3ZaGHpjzTDdgJm.hxt6TELcPiJAsAOBYizC - 15.PpPHKolFtN' } headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', 'cookie': 'tt_webid=6844895200352765453; ttcid=147baf1d0de44bcfaa3aaccb43de319231; csrftoken=e72569f7c754e03b930bbb54f34b7759; WEATHER_CITY=%E5%8C%97%E4%BA%AC; tt_webid=6845096485504583176; s_v_web_id=verify_kc5ojvq4_iZKfsEzB_AubR_44PZ_AgkE_hvFA5OJnJ4nc; SLARDAR_WEB_ID=ba4439ab-f467-42a9-9dcd-8be836757cc3; __tasessionId=mbg1eigaz1593748245904; tt_webid=6845096485504583176; __ac_nonce=05efeab2d00f5555e228f; __ac_signature=_02B4Z6wo00f01JctsQwAAIBDjnNXOcxFq8yXKbWAAHs9kTU3N2TXnkkV75OXvSXoT5pfhWopyS8N2zbrE1VOQlMWB8pFBr0ZvUmL9qtI0GvgW6d9cv9TeAEXgf1HZ3bDCooMMUBc9Rq-r53241; tt_scid=8TNWiPBmsnVRkGGZJ5frIVGKsH4gMngyY0s4KQWdyckfgNuI45yMdiqvIa1sudDF15e8' } url = 'https://www.toutiao.com/api/search/content/?' + urlencode(para) # urlencode可以吧字典类型转化为url中的请求参数 try: response = requests.get(url, headers=headers) if response.status_code == 200: print('索引页请求成功') response.encoding = 'UTF-8' return response.text return None except RequestException: print('索引页请求失败') return None二、解析索引页数据。由于这个数据是在js中存储的,一般的爬虫库并不适用,所以我们使用正则表达式的方法将他匹配出来,然后取出各个索引的Url与Title。 ...

July 4, 2020 · 3 min · jiezi

AtCoder-Context-ABC-172-D-Sum-of-Divisors

本文章为原创文章,未经过允许不得转载运行要求 运行时间限制: 2sec 内存限制: 1024MB 原题链接 题目给定一个正整数X,正整数的X的约数的函数为f(X)给定一个正整数N,求F(1)x1 + F(2)x2 .... + F(N)xN 输入前提条件 1 <=N <= 10000000输出输出 F(1)x1 + F(2)x2 .... + F(N)xN 例1 输入 4输出 23f(1) = 1f(2) = 2f(3) = 2f(4) = 3所以最终的结果是1x1 + 2x2 + 2x3 + 3x4 = 1 + 4 + 6 + 12 = 23 例2输入 100输出 26879例3输入 10000000输出 838627288460105注意溢出问题 读懂题目从1到N,每个数乘以这个数约数的个数,然后相加N最大可以达到10的7次方,所以,不能用o(N*N)的复杂度 解题思路如图所示,我们以N=6为例。1到6的每个数的约数都在下面的方块中显示因为最终要求的是f(1)x1 + f(2)x2 + f(3)x3 + f(4)x4 + f(5)x5 + f(6)x6 ...

June 30, 2020 · 1 min · jiezi

微博自动发微博脚本

git仓库地址:https://github.com/MasakiOvO/weibo-create-new-post weibo-create-new-post使用 selenium 写成的 自动发微博脚本 安装依赖需要在国内服务器上运行脚本 pip install -r requirements.txt 配置cp config/user.config.example config/user.config修改config/user.config内的参数 启动脚本python index.py微博内容设置在config/message.txt 默认设置的是一些土味情话。 设置定时任务我设置的是每天8点发一条微博 00 08 * * * python3 /www/weibo-auto-new-post/index.py效果

June 30, 2020 · 1 min · jiezi

Python爬虫Selenium和动作链实现淘宝模拟登录

一、准备话不多说,咋们先来看看淘宝登陆页面,可以看到登陆网址太长了,但其实"?"后面的可以是舍弃的,得到https://login.taobao.com/member/login.jhtml 就登陆而言页面默认是密码登录,也给我们少去了一些麻烦,目前来说只要找到使用Selenium找到账号和密码框赋值后,再点击登录按钮就可以实现淘宝模拟登录了,但事实并非如此,我们接着往下看。在我使用如下代码进行测试登陆的时候,惊奇的发现多出来了滑块验证码。区区滑块验证码算啥,撸起袖子就是干!!! from selenium import webdriverimport timefrom PIL import Imagefrom selenium.webdriver import ActionChains#初始def main(): bro = webdriver.Chrome() bro.maximize_window() bro.get("https://login.taobao.com/member/login.jhtml") time.sleep(1) bro.find_element_by_name("fm-login-id").send_keys("淘宝账号") time.sleep(1) bro.find_element_by_name("fm-login-password").send_keys("淘宝密码") time.sleep(1) time.sleep(10)if __name__ == "__main__": main() 想要破解滑块验证码其实不难,大体来说肯定是要找到滑块验证码然后使用动作链进行点击滑动,然后再点击登录就OK了。那接下来开始代码分析。 二、代码分析第一部分 #初始def main(): bro = webdriver.Chrome() bro.maximize_window() bro.get("https://login.taobao.com/member/login.jhtml") #get方式请求淘宝登陆页面 time.sleep(1) #休眠一秒,不要太快 bro.find_element_by_name("fm-login-id").send_keys("淘宝账号") 根据name找到账号input标签 time.sleep(1) bro.find_element_by_name("fm-login-password").send_keys("淘宝密码") 根据name找到密码input标签 time.sleep(1) GetImage(bro) #得到滑块截图第二部分 #获取def GetImage(bro): # save_screenshot 就是将当前页面进行截图且保存 bro.save_screenshot('taobao.png') code_img_ele = bro.find_element_by_xpath("//*[@id='nc_1__scale_text']/span") #根据xpath语法找到滑块验证码 location = code_img_ele.location #验证码图片左上角的坐标 x,y size = code_img_ele.size # 验证码的标签对应的长和宽 # 左上角和右下角的坐标 rangle = ( int(location['x']),int(location['y']),int(location['x'] + size['width']),int(location['y'] + size['height']) ) i = Image.open("./taobao.png") # code_img_name = './tb.png' # crop裁剪 frame = i.crop(rangle) #得到滑块验证码图片 # frame.save(code_img_name) Action(bro,code_img_ele) #执行注意截图时机,登录页面一开始加载后滑块验证码并不会出现,等到账号和密码输入后才会出现,所以截图的时机要放在账号和密码输入之后。 ...

June 28, 2020 · 2 min · jiezi

AtCoder-Context-ABC-171-E-Red-Scarf

本文章为原创文章,未经过允许不得转载运行要求 运行时间限制: 2sec 内存限制: 1024MB 原题链接 题目小明有N只猫,N为偶数。给每个猫一个编号从1到N。每个猫给一个标牌,标牌上面写着一个非负整数。小明最近在学习异或运算xor。XOR的定义 对于N个非负整数x1,x2,x3...xN,这些数的异或 x1 xor x2 xor x3...xor xN按照下面的方式定义x1 xor x2 xor x3 ... xor xn,把他们用2进制表示。对应的位数上的1的个数为奇数的话,那么该位的结果为1,对应的位数的1的个数为偶数的话,该位的结果为0小明在给猫的标牌上写数字的时候,赶快用一下刚刚学到的xor异或运算。 现在给1到N号猫另外一串特殊编号ai。 这里的ai表示,除了i号猫以外,其他的猫的标牌号的xor运算结果。 我们给定1到N号猫的特殊编号a1,a2,a3....aN 请根据ai求出,每个小猫的标牌号。 输入前提条件 所有的输入均为整数2 <= N <= 200000N为偶数0 <= ai <= 1000000000给出的输入都能够找到相应的输出输入 Na1 a2 … aN输出 输出一行,里面包含用空格分开的N个标牌号从左往右第i个数字代表第i只猫的标牌号满足条件的结果由多个的话,输出任意的结果 例1 输入 420 11 9 24输出 26 5 7 22按照上面输出的标牌号,非自身以外的标牌号的xor结果,满足给定条件ai 5 xor 7 xor 22 = 2026 xor 7 xor 22 = 1126 xor 5 xor 22 = 926 xor 5 xor 7 = 24读懂题目xor 用^来代替 ...

June 22, 2020 · 2 min · jiezi

Python-reStructuredText-帮助文件中文乱码

在使用 IntelliJ 对 reStructuredText 文件进行编辑的时候。 我们可能会遇到乱码的情况。 如下图: 可以看到,我们在使用 IntelliJ 的时候中文是乱码的。 这里有几个地方是需要修改的,首先你需要修改你的项目使用的是 UTF-8 编码。 Ctrl + Alt + S 进入设置,然后选择 Editor > File Encodings 你需要将你的全局设置,项目编码都设置成 UTF-8,如果你使用的是中文操作系统,可能这里默认设置是 GBK,不要使用 GBK。 然后重启你的 IntelliJ, 你可能会发现你的修改没有生效。 这是因为 reStructuredText 的插件使用了 Java 的 JavaFX 或者 Swing,这在默认情况下是不支持 UTF-8 的。 你需要对 IntelliJ 的启动参数进行设置。 选择帮助下面的修改自定 VM 选项。 在文件的最后添加 -Dfile.encoding=UTF-8这个表示的是在 IntelliJ 启动的时候,我们将 VM 的启动参数强制使用 UTF-8 编码。 在完成上面的修改后,重启你的 IntelliJ,然后在对文件进行对比查看。 你可以看到你的 IntelliJ 已经能够支持中文了。 因为你 IntelliJ 是基于 Java 平台,Java 平台中的 JavaFX 和 Swing 对 UTF-8 的支持一种不是非常理想,不是开箱即用的那种。 ...

June 17, 2020 · 1 min · jiezi

AtCoder-Context-ABC-079-D-Wall

本文章为原创文章,未经过允许不得转载运行要求 运行时间限制: 2sec 内存限制: 1024MB 未经允许,不得许转载原题链接 题目魔法少女想要把这个世界上所有的数字都变为1把一个数字从i变成j需要cij个魔法点数。0<=i,j<=9现在面前有一堵墙,宽为W,高为H。只要有一个砖块里写着0以上9以下的整数。从上往下,从左往右i行(1<=i<=H),第j列(1<=j<=W),写着数情报Aij Aij = -1 的情况下,代表砖头上没有写数字Aij != -1 的情况下,代表砖头上写着数字Aij求把墙壁上所有的数字都变成1,所需要的最小魔法值。 输入前提条件 所有的输入均为整数1 <= H,W <= 200cij = 0 (i = j)-1 <= Aij <= 9墙上至少写了一个整数输入 输入按照以下形式标准输入 H Wc0,0 ... c0,9::c9,0 ... c9,9A1,1 ... A1,W:AH,1 ... AH,W输出输出把墙壁上所有的数都变成1,所需要的最小魔法值 例1 输入 2 40 9 9 9 9 9 9 9 9 99 0 9 9 9 9 9 9 9 99 9 0 9 9 9 9 9 9 99 9 9 0 9 9 9 9 9 99 9 9 9 0 9 9 9 9 29 9 9 9 9 0 9 9 9 99 9 9 9 9 9 0 9 9 99 9 9 9 9 9 9 0 9 99 9 9 9 2 9 9 9 0 99 2 9 9 9 9 9 9 9 0-1 -1 -1 -18 1 1 8输出 ...

June 10, 2020 · 3 min · jiezi

解决问题matplotlib-生成的图像中无法显示中文字符

matplotlib 生成的图像中无法显示中文字符开发环境windows 8.1 64bitpython 3.6.0matplotlib 3.2.1问题背景使用 matplotlib 绘制函数图像的时候,发现设置图像名称或图例需要汉字显示的时候只能得到空格生成图像中的中文错误效果 原因分析python中的matplotlib仅支持Unicode编码,默认是不显示中文的.解决方案解决方案1python文件中添上一段语句plt.rcParams['font.sans-serif']=['Simhei']之后再次运行得出图像 解决方案2制定加载本地的字体文件在python文件中导入matplotlib的字体控制方法 from matplotlib.font_manager import FontProperties 另设font变量存储设置好的属性 font = FontProperties(fname=r'C:\Windows\Fonts\simhei.ttf',size=14) 设置 title 内容时将 font的存储对象赋给 fontproperties 属性 plt.title(u'y=x 与 y=x^0.5 的函数图像比较',fontproperties = font)修改源码后生成的图像 附件修改前的 python 文件 import numpy as np import matplotlib.pyplot as plt x = np.linspace(0,100) # 设置自变量的取值[0,100] y1 = x y2 = x**0.5 plt.figure() plt.plot(x,y1,label='y=x') plt.plot(x,y2,label='y=x^0.5',color='red') plt.title('y=x 与 y=x^0.5 的函数图像比较') plt.legend() plt.show()经解决方案1修改后的源码 import numpy as np import matplotlib.pyplot as plt x = np.linspace(0,100) # 设置自变量的取值[0,100] y1 = x y2 = x**0.5 plt.figure() plt.plot(x,y1,label='y=x') plt.plot(x,y2,label='y=x^0.5',color='red') plt.title('y=x 与 y=x^0.5 的函数图像比较') plt.rcParams['font.sans-serif']=['Simhei'] plt.legend() plt.show()经解决方案2修改后的源码 import numpy as np from matplotlib.font_manager import FontProperties import matplotlib.pyplot as plt x = np.linspace(0,100) # 设置自变量的取值[0,100] y1 = x y2 = x**0.5 plt.figure() plt.plot(x,y1,label='y=x') plt.plot(x,y2,label='y=x^0.5',color='red') font = FontProperties(fname=r'C:\Windows\Fonts\simhei.ttf',size=14) plt.title(u'y=x 与 y=x^0.5 的函数图像比较',fontproperties = font) plt.legend() plt.show()

June 10, 2020 · 1 min · jiezi

AtCoder-ContextABC-084-D-2017like-Number

本文章为原创文章,未经过允许不得转载运行要求 运行时间限制: 2sec 内存限制: 1024MB 未经允许,不得许转载原题链接 题目如果有一个奇数N,N和(N+1//2)都是素数的话,N为2017的相似数现在给定Q次查询第i(1<=i<=Q)次查询,第i次查询给定奇数li,ri,求li<=x<=ri范围内,2017相似数的x的个数 输入前提条件 1<=Q<=1000001<=li<=ri<=100000li,ri为奇数所有的输入都为整数输入 输入按照以下形式标准输入 Ql1 r1l2 r1...lQ rQ输出第i行输出,第i次查询的结果 例1 输入 13 7输出 23和((3+1)/2)都为素数,所以3为2017的相似数5和((5+1)/2)都为素数,所以5为2017的相似数7虽然是素数,但是5((7+1)/2)不是素数,所以7不是2017的相似数以上所述,查询1的结果为2 例2输入 413 137 117 112017 2017输出 1001注意2017也是2017的相似数 例2输入 61 5313 9137 5519 5173 9113 49输出 441112读懂题目给定一个区间,在这个区间的所有素数当中,挑选出折半以后仍然是素数的数字 解题思路首先我们要看到li,ri的最大值是100000,最小值是1li,ri决定了区间的左边界和右边界所以区间的最大跨度是1到100000 首先我们要找到这个区间里面的所有的素数因为是代码竞技所以不能使用第三方的扩展包我们手写素数生成器具体的方法用到素数筛选法英文叫sieve of Eratosthenes 我们取一串区间,记住最少要从2开始。我们找出这串数字的最小的元素,这里为2先找出2的倍数,然后去掉它们 在从剩下的里面找第1个没有被遍历的元素,这里是3找出3的倍数,然后去掉它们 依此类推,找出5的倍数,去掉他们 有的时候,最小元素的倍数不存在了,那么什么都不用做 以这种方式可以找到所有的素数 但是有一点要注意的是,遍历结束的标志。区间从2到某个地方的方start可以从区间的开头遍历到区间的结尾,但是如果区间很大的话,我们只需要遍历到区间的平方根的地方就好了比如2-16的话我们只需要遍历到2-42-100的话我们只需要遍历到2-10 好,我们拿到了1-100000的所有的素数 我们再次遍历一次1-100000,判断每一个数是不是2017的相似数用累积和的求法,算出从1到遍历点i的相似数的个数 具体就是如果i为2017的相似数,那么1到i的2017相似数的个数 = 1到(i-1)的2017相似数的个数 + 1 具体就是如果i不是2017的相似数,那么1到i的2017相似数的个数 = 1到(i-1)的2017相似数的个数 最后对于区间(li,ri)内2017相似数的个数的统计=1到ri的2017相似数的个数 - 1到(li-1)的2017相似数的个数 代码 import mathdef sushu(n): arr = [] for i in range(2, n + 1): arr.append(i) limit = int(math.sqrt(n)) + 1 prev = [] while True: start = arr[0] prev.append(start) if start > limit: break brr = [] for i in arr: if i % start != 0: brr.append(i) arr = brr prev.extend(arr) return prevn = 100000shushu = sushu(100000)marks = []for i in range(n + 1): marks.append(False)for j in shushu: marks[j] = Truemarks2 = []result = []for i in range(n + 1): if i % 2 == 0: marks2.append(False) if i == 0: result.append(0) else: result.append(result[i - 1]) else: if marks[(i + 1) // 2] and marks[i]: marks2.append(True) result.append(result[i - 1] + 1) else: marks2.append(False) result.append(result[i - 1])Q = int(input())ARR = []for i in range(Q): ARR.append(list(map(int, input().split())))for i in range(Q): start = ARR[i][0] end = ARR[i][1] print(result[end] - result[start - 1])总结这道题考察了对素数的求法。运用素数筛选法可以求出某一个区间以内的所有的素数 ...

June 6, 2020 · 1 min · jiezi

多线程拉取impala数据到本地

import threadingimport timefrom impala.dbapi import connectimport pandas as pdimport osclass MyThread(threading.Thread): def __init__(self, threadid, name, day, min): threading.Thread.__init__(self) self.threadID = threadid self.name = name self.day = day self.min = min def run(self): print("开始线程:" + self.name) run_task(self.name, self.day, self.min) print("退出线程:" + self.name)def run_task(thread_name, day, min): hour = 24 while hour: if hour < 11: _hour = '0' + str(hour - 1) else: _hour = hour - 1 try: query_and_write(day, _hour, min) except Exception as e: print(str(day) + str(_hour) + '-----need--rey--try-' + str(e)) time.sleep(10) continue time.sleep(2) print("%s: %s" % (thread_name, time.ctime(time.time()))) hour -= 1def impala_conn_exec(sql): conn = connect(host='*.*.*.*', port=21050) cur = conn.cursor() cur.execute(sql) cur.close result = cur.fetchall() return resultdef query_and_write(_date, _hour, _min): """ 初始化sql,调用查询并写入CSV :param _date: :param _time: :return: """ sql = "select * " \ "from 表名 m where date= '{0}' " \ "and substr(cast(time as string),1,15) = '{0} {1}:{2}'/*SA(production)*/".format(_date, _hour, _min) print(sql) result = impala_conn_exec(sql) # result = [] df = pd.DataFrame(data=result) path = _date if os.path.exists(path): pass else: os.mkdir(path) file_name = "data_{0}-{1}-{2}.csv".format(_date, _hour, _min) df.to_csv(path + '/' + file_name, encoding="utf-8", index=False)# 按日期范围循环 遍历区间开闭示意: [起始日期,截止日期)for j in range(5, 7): daterange = "2020-02" if j < 10: daterange = daterange + "-0" + str(j) else: daterange = daterange + "-" + str(j) print(daterange) # 创建新线程 threads = [] for i in range(0, 6): if i < 10: id = "thread0" + str(i) else: id = "thread" + str(i) threadName = MyThread(1, id, daterange, i) threads.append(threadName) try: # 启动线程 for thread in threads: thread.setDaemon(True) thread.start() time.sleep(1) # 等待所有线程结束 for thread in threads: thread.join() except Exception as e: print(e) j += 1print("退出主线程")

June 5, 2020 · 2 min · jiezi

Python之pandas

dataframe和series操作1、取dataframe数据1) iterrows()for index_, row in df1.iterrows(): print(index_) print(row, row.values[0])iterrows()按行遍历dataframe或series,返回两个元素:行索引和行值,其中行值为Series格式,可以根据list索引取具体的数值。结果: 2) itertuples()itertuples为每一行产生一个namedtuple,并且行的索引值作为元组的第一个元素,pandas类型。 for nametuple in df1.itertuples(): print(nametuple) print(nametuple[0], type(nametuple))3) dataframe按某列的值取数据temp_df[temp_df.c1 == 'aa']['c2']dataframe对象temp_df的c1列值为aa时temp_df的c2列的值; 4) dataframe根据列值取行索引temp_df[temp_df.c1 == 'aa'].index.to_list()temp_df的c1列值为aa时,temp_df的行的索引; 5) dataframe 根据行索引和列名修改dataframe的值final_result.loc[10, 'c1'] = abc将final_result的10行c1列的值改为abc; 6) dataframe根据列名取值sorted(list(set(pre_result['c3'].to_list())))返回list格式,set()去重,list()改回list格式,sorted()排序; 7) 取dataframe的部分列df_after[['c1', 'c3', 'c6']]8) dataframe.loc[0]——根据数字型行索引的值取值,print(retemp.loc[0])retemp: asset_return asset_vol0 1 21 11 12output:asset_return 1asset_vol 29) dataframe.iloc[1]——根据行顺序取值,取第i行,从0开始retemp: asset_returnasset_vol b aee ddoutput:asset_return ddasset_vol ee2、索引1) 修改列名或索引名df_after = df_after.rename(columns={base_type: 'values'})修改列名base_type为’values’。 2) dataframe.set_index('return')——将return列的值作为新的行索引print(retemp, '\n', retemp.set_index('return'))output: return asset_vol0 a b1 dd ee returnasset_vol b aee dd 3) dataframe.reset_index()重置行索引为数字型索引,参数drop=True时丢失原索引列,参数inplace=True时,修改原df,为false时,返回新的df ...

November 3, 2019 · 2 min · jiezi

500行代码教你用python写个微信飞机大战

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。 帮助蹲厕族、YP族、饭圈女孩在无聊之余可以有一样东西让他们振作起来!让他们的左手 / 右手有节奏有韵律的朝着同一个方向来回移动起来! 这是史诗级的发明,是浓墨重彩的一笔,是…… 在一阵抽搐后,我结束了游戏,瞬时觉得一切都索然无味,正在我进入贤者模式时,突然想到,如果我可以让更多人已不同的方式体会到这种美轮美奂的感觉岂不美哉? 所以我打开电脑,创建了一个 plan_game.py…… 先看效果图 操作环境操作系统:windows10python版本:python 3.7代码编辑器:pycharm 2018.2使用模块:os,sys,random,pygame因为实现代码使用到了一个pygame的第三方模块,没有的先 pip install 一下,这里顺便提供一个比较好的pygame的教程. https://eyehere.net/2011/python-pygame-novice-professional-index/ 具体实现首先我们先指定素材文件的文件目录.方便我们后面的使用。这些素材已经全部上传至公众号Python专栏,后台回复:飞机大战,即可获得。import os# 得到当前文件夹下面的material_images目录的路径source_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'material_images')实现一个Game类,用来完成这个游戏的主要逻辑。import pygameclass Game(): def __init__(self, background_image_path, size=(480, 700), title='飞机大战', font_name='方正舒体', font_size=30, speed=2000): ''' :param background_image_path: 背景图片的路径地址 :param size: 游戏窗口的大小 :param title: 游戏窗口的标题 :param font_name: 指定字体 :param font_size: 指定字体大小 :param speed: 背景图滚动整个窗口一次所用时间,单位为ms ''' self.size = size self.screen = pygame.display.set_mode(size) self.title = title self.background_image_path = background_image_path self.background = pygame.image.load(self.background_image_path).convert() # 设置字体对象,得到系统中自带的字体 self.font = pygame.font.SysFont(font_name, font_size) # 得到Clock对象,我们可以使用它来获取距离上次绘制图像的时间 self.clock = pygame.time.Clock() # 背景图初始位置 self.height = 0 # 使用窗口的高度处于滚动的时间,就能得到每ms滚动的距离 self.every_ms_move_distance = self.size[1] / speed # 2秒 # 分数 self.score = 0 # 存放所有的敌机 self.enemies = [] def show_score(self): ''' 显示分数, 在窗口的的最上方距离上边距10px, 左右居中 ''' pass def set_time_passed(self): # 控制画 的帧, 越大越快 # 得到上一次绘制图像到到现在的时间, ms self.time_passed = self.clock.tick() def draw_background(self): ''' 绘制背景图片,一直向下滚动,营造飞机一直往上面飞的感觉 ''' # 每次移动的距离 = 每ms移动的距离 * 上次到现在的时间(ms) pass def create_enemy(self, image_path=os.path.join(source_dir,'enemy1.png'), enemy_number=5): ''' 创建敌机 :param image_path: 敌机的图片地址 :param enemy_number: 最多有几个敌机在屏幕上 ''' pass def draw_enemies(self, time_passed, screen): ''' 绘制敌机到屏幕上,清理跑出窗口的敌机, :param time_passed: 上次绘制导向现在经过的时间 :param screen: 绘制的窗口对象 ''' pass def bullet_and_enemy_crash_detection(self, bullets): ''' 检测子弹是否击中敌机 :param bullets: 飞机的所有子弹 ''' pass def plan_and_enemy_crash_detection(self, plan, allow_crash_size=None): ''' 检测敌机与飞机是否相撞 :param plan: 飞机对象 :param allow_crash_size: 允许飞机碰撞的大小,只有左右有效 ''' pass def draw_plan(self, plan, time_passed): ''' 绘制飞机 :param plan: 飞机对象 :param time_passed: 距离上次绘制的时间 :return: ''' pass def game_over(self): ''' 游戏结束 ''' while True: # 绘制背景图 pass def run(self): ''' 游戏入口函数,开始函数,主体函数 :return: ''' # 设置游戏窗口的大小 pygame.display.set_caption(self.title) # 初始化一个飞机对象 plan = Plan() while True: # 如果飞机自毁完成, 游戏结束, 调用game_over函数 pass # 检测监听事件 pass # 检测上下左右的移动案件. # w,a,s,d 和 上,下,左,右键都可以 # 然后执行plan.update函数,改变飞机的位置 pass # 子弹和敌机的碰撞检测 self.bullet_and_enemy_crash_detection(plan.bullets) # 飞机与敌机的碰撞检测 self.plan_and_enemy_crash_detection(plan) # 设置属性time_passed的值, 距离上次的时间,方便后面使用 self.set_time_passed() # 绘制背景图片 self.draw_background() # 显示分数 self.show_score() # 生成敌机 self.create_enemy() # 绘制敌机 self.draw_enemies(time_passed=self.time_passed, screen=self.screen) # 绘制飞机 self.draw_plan(plan=plan, time_passed=self.time_passed) # 绘制子弹 plan.draw_bullets(time_passed=self.time_passed, screen=self.screen) # 显示我们的图像 pygame.display.update()这里说以下怎样查看自己的系统中有哪些自带的字体.pygame.font.get_fonts(),这个函数就能够得到系统中所有的自带字体文件。不过,当我们游戏中有中文的时候,我们也得选择支持中文的字体,否则的话是显示不出中文的。 ...

October 16, 2019 · 3 min · jiezi

Django22中间件详解

中间件是 Django 用来处理请求和响应的钩子框架。它是一个轻量级的、底层级的“插件”系统,用于全局性地控制Django 的输入或输出,可以理解为内置的app或者小框架。 在django.core.handlers.base模块中定义了如何接入中间件,这也是学习Django源码的入口之一。 每个中间件组件负责实现一些特定的功能。例如,Django 包含一个中间件组件 AuthenticationMiddleware,它使用会话机制将用户与请求request关联起来。 中间件可以放在你的工程的任何地方,并以Python路径的方式进行访问。 Django 具有一些内置的中间件,并自动开启了其中的一部分,我们可以根据自己的需要进行调整。 一、如何启用中间件若要启用中间件组件,请将其添加到 Django 配置文件settings.py的 MIDDLEWARE 配置项列表中。 在 MIDDLEWARE 中,中间件由字符串表示。这个字符串以圆点分隔,指向中间件工厂的类或函数名的完整 Python 路径。下面是使用 django-admin startproject命令创建工程后,默认的中间件配置: MIDDLEWARE = [  'django.middleware.security.SecurityMiddleware',  'django.contrib.sessions.middleware.SessionMiddleware',  'django.middleware.common.CommonMiddleware',  'django.middleware.csrf.CsrfViewMiddleware',  'django.contrib.auth.middleware.AuthenticationMiddleware',  'django.contrib.messages.middleware.MessageMiddleware',  'django.middleware.clickjacking.XFrameOptionsMiddleware', ]实际上在Django中可以不使用任何中间件,如果你愿意的话,MIDDLEWARE 配置项可以为空。但是强烈建议至少使用 CommonMiddleware。而笔者的建议是保持默认的配置,这有助于你提高网站的安全性。 二、 中间件最关键的顺序问题MIDDLEWARE 的顺序很重要,具有先后关系,因为有些中间件会依赖其他中间件。例如: AuthenticationMiddleware 需要在会话中间件中存储的经过身份验证的用户信息,因此它必须在 SessionMiddleware 后面运行 。 在请求阶段,调用视图之前,Django 按照定义的顺序执行中间件 MIDDLEWARE,自顶向下。 你可以把它想象成一个洋葱:每个中间件类都是一个“皮层”,它包裹起了洋葱的核心--实际业务视图。如果请求通过了洋葱的所有中间件层,一直到内核的视图,那么响应将在返回的过程中以相反的顺序再通过每个中间件层,最终返回给用户。 如果某个层的执行过程认为当前的请求应该被拒绝,或者发生了某些错误,导致短路,直接返回了一个响应,那么剩下的中间件以及核心的视图函数都不会被执行。 三、Django内置的中间件Django内置了下面这些中间件,满足了我们一般的需求: Cache缓存中间件 如果启用了该中间件,Django会以CACHE_MIDDLEWARE_SECONDS 配置的参数进行全站级别的缓存。 Common通用中间件 该中间件为我们提供了一些便利的功能: 禁止DISALLOWED_USER_AGENTS中的用户代理访问服务器自动为URL添加斜杠后缀和www前缀功能。如果配置项 APPEND_SLASH 为True ,并且访问的URL 没有斜杠后缀,在URLconf中没有匹配成功,将自动添加斜杠,然后再次匹配,如果匹配成功,就跳转到对应的url。 PREPEND_WWW 的功能类似。为非流式响应设置Content-Length头部信息。作为展示的例子,这里额外贴出它的源代码,位于django.middleware.common模块中,比较简单,很容易读懂和理解: class CommonMiddleware(MiddlewareMixin): """ 去掉了doc """ response_redirect_class = HttpResponsePermanentRedirect def process_request(self, request): # Check for denied User-Agents if 'HTTP_USER_AGENT' in request.META: for user_agent_regex in settings.DISALLOWED_USER_AGENTS: if user_agent_regex.search(request.META['HTTP_USER_AGENT']): raise PermissionDenied('Forbidden user agent') # Check for a redirect based on settings.PREPEND_WWW host = request.get_host() must_prepend = settings.PREPEND_WWW and host and not host.startswith('www.') redirect_url = ('%s://www.%s' % (request.scheme, host)) if must_prepend else '' # Check if a slash should be appended if self.should_redirect_with_slash(request): path = self.get_full_path_with_slash(request) else: path = request.get_full_path() # Return a redirect if necessary if redirect_url or path != request.get_full_path(): redirect_url += path return self.response_redirect_class(redirect_url) def should_redirect_with_slash(self, request): if settings.APPEND_SLASH and not request.path_info.endswith('/'): urlconf = getattr(request, 'urlconf', None) return ( not is_valid_path(request.path_info, urlconf) and is_valid_path('%s/' % request.path_info, urlconf) ) return False def get_full_path_with_slash(self, request): new_path = request.get_full_path(force_append_slash=True) if settings.DEBUG and request.method in ('POST', 'PUT', 'PATCH'): raise RuntimeError( "You called this URL via %(method)s, but the URL doesn't end " "in a slash and you have APPEND_SLASH set. Django can't " "redirect to the slash URL while maintaining %(method)s data. " "Change your form to point to %(url)s (note the trailing " "slash), or set APPEND_SLASH=False in your Django settings." % { 'method': request.method, 'url': request.get_host() + new_path, } ) return new_path def process_response(self, request, response): # If the given URL is "Not Found", then check if we should redirect to # a path with a slash appended. if response.status_code == 404: if self.should_redirect_with_slash(request): return self.response_redirect_class(self.get_full_path_with_slash(request)) if settings.USE_ETAGS and self.needs_etag(response): warnings.warn( "The USE_ETAGS setting is deprecated in favor of " "ConditionalGetMiddleware which sets the ETag regardless of " "the setting. CommonMiddleware won't do ETag processing in " "Django 2.1.", RemovedInDjango21Warning ) if not response.has_header('ETag'): set_response_etag(response) if response.has_header('ETag'): return get_conditional_response( request, etag=response['ETag'], response=response, ) # Add the Content-Length header to non-streaming responses if not # already set. if not response.streaming and not response.has_header('Content-Length'): response['Content-Length'] = str(len(response.content)) return response def needs_etag(self, response): """Return True if an ETag header should be added to response.""" cache_control_headers = cc_delim_re.split(response.get('Cache-Control', '')) return all(header.lower() != 'no-store' for header in cache_control_headers)GZip内容压缩中间件 ...

August 7, 2019 · 4 min · jiezi

ubuntu下使用URLOS-5分钟快速部署Python3网站环境

本文主要介绍如何在ubuntu下快速部署Python3网站环境,不需要一步一步手工部署,借助URLOS面板即可实现5分钟快速部署。让我们正式开始吧! 首先通过以下命令安装URLOS面板: curl -LO www.urlos.com/siu && sh siu面板安装完成后,登录URLOS,在应用市场中搜索python3网站环境,点击安装按钮: 在基本信息中填写服务名称、运行节点、端口号: 在网站中填写网站域名、引导文件等: 完成以上步骤后,点击提交即可。等待系统自动部署完成。 部署完成后,在浏览器中访问: 本文介绍了如何使用URLOS快速部署Python3网站环境,对URLOS感兴趣的朋友可以关注一下。

July 15, 2019 · 1 min · jiezi

python一起学python1

python跟很多前端工作者一样,我也常常打听。作为前端,在要懂js的前提下,还要可以学什么其他语言来增加自己的竞争力。 我看到最多的是node,很多人说前端真正的学好node。已经可以胜任很多工作了。假如想学后端java是需求最大的。 不过目前来说java的学习成本很高,相对python是一门很好入门的语言,最近也是很火。 所以我想用一小段时间,快速了解一下python。(本文用的是python3.x) 数据类型先看数据类型(看我们可以pyhton中写什么。) 整数浮点数字符串布尔值空值乍一看基本类型和js的差不多。在学习过程中我们会多次用到print();类似于js的console,就是打印输出。 声明python的声明没有关键字,声明和赋值写法一样。 counter = 100 # 整型变量miles = 1000.0 # 浮点型变量name = "John" # 字符串变量flag = True # 布尔类型变量print(counter) //100print(miles) //1000.0print(name) //"John"print(flag) //True这种常用的是动态语言,与之相反的是静态语言。在声明时规定变量的类型。 int a = 123; // a是整数类型变量a = "ABC"; // 会报错,不能把字符串赋给整型变量格式化相当于占位符,用%符号调用。 `'Hello, %s' % 'world'// 'Hello, world'各种占位符 %d 整数%f 浮点数%s 字符串%x 十六进制整数其中当用到%时,需要转义一下。%% >>> 'growth rate: %d %%' % 7'growth rate: 7 %'listlist很像js中的数组。这里叫列表。其实也差不多,就是一个有序的存放数据的表。 >>> classmates = ['Michael', 'Bob', 'Tracy']print(classmates)//['Michael', 'Bob', 'Tracy']用len()可以查看list的长度(同时也能看字符的长度) ...

July 12, 2019 · 2 min · jiezi

Python-实现简单网络应用程序开发

最后一次更新于 2019/07/10 ICMP Ping目的此任务是重新创建第3讲(延迟,丢失和吞吐量)中讨论的ping客户端。Ping 是一个用于在计算机网络中测量延迟和丢失的工具。在实际应用中,我们可以通过 ping 命令分析判断网络失败的原因。当然,这类信息也可用于帮助我们选择性能更佳的IP地址作为代理服务器。 原理Ping 通常使用 Internet 控制消息协议 (ICMP) 报文来测量网络中的延迟和丢失:本机在 ICMP 包中发送回响请求(ICMP类型代码为8)给另一个主机。然后,主机解包数据包并提取ICMP类型代码并匹配请求和回复之间的ID。如果远程主机的响应报文ICMP类型代码为0,然后我们可以计算发送请求和接收回复之间经过的时间,进而精确的计算两台主机之间网络的延迟。 注意: IP数据报和ICMP错误代码的结构(ICMP类型代码为3)如下所示。因特网校验和也是数据包的重要部分,但它不是本函数实现的核心。 函数实现基于上述原理,首先,需要创建一个与协议ICMP关联的套接字,并设置超时以控制用于接收数据包的时间套接字。 # 运行特权TCP套接字,1是与协议ICMP关联的套接字模块常量。icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, 1)icmp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeout)创建套接字后,需要实现一个函数来构建,打包并将ICMP数据包发送到目标主机。如图所示,如果创建一个32字节大小的数据包,那么只有四个字节长度来存储有效负载数据。因此,以浮点格式(4个字节)存储当前时间帧是比较好的解决办法。但是,由于精度损失,不能使用此数据来计算总网络延迟。 "!" 但是,由于精度损失,我永远不会使用此数据来计算总网络延迟。 构建和打包ICMP数据包源代码: def receive_one_ping(icmp_socket, port_id, timeout, send_time): while True: # 1. 等待套接字并得到回复。 wait_for_data = select.select([icmp_socket], [], [], timeout) # 2. 一旦接受,记录当前时间。 data_received = time.time() rec_packet, addr = icmp_socket.recvfrom(1024) ip_header = rec_packet[8: 12] icmp_header = rec_packet[20: 28] payload_size = struct.calcsize("!f") # 3. 解压包首部行查找有用的信息。 type, code, checksum, id, sequence = struct.unpack("!bbHHh", icmp_header) # 4. 检查收发之间的 ID 是否匹配。 if type == 0 and id == port_id: # type should be 0 ttl = struct.unpack("!b", ip_header[0:1])[0] delay_time = data_received - send_time # 5. 返回比特大小,延迟率和存活时间。 return payload_size * 8, delay_time, ttl elif type == 3 and code == 0: return 0 # 网络无法到达的错误。 elif type == 3 and code == 1: return 1 # 主机无法到达的错误。当从同一主机获得所有ping测试结果时,需要另一个函数来显示所有测量的最小时间,平均时间和最大延迟。 ...

July 10, 2019 · 11 min · jiezi

pythonrequests爬取知乎个人信息数据

效果预览地址:http://23.105.208.123/ 技术栈python3requestsredisechart源码地址https://github.com/MasakiOvO/... python需要安装的库requests,BeautifulSoup,redis,django 思路两个程序。 一个程序负责爬取用户关注和粉丝列表, 并把用户名存入set另一个程序负责根据用户名获取详细信息,存入hash维护 两个列表 1.已爬用户 2.未爬用户第一个程序的流程: 当未爬set不为空时:执行如下操作:每次从未爬取列表中取出一个用户名 根据用户名,获取他的关注与粉丝并遍历,如果用户既没在已爬用户,也没在未爬用户 加入未爬用户列表。第二个程序的流程 每次从未爬set中取出一个用户名,调用接口获取详细信息并存入redis hash中接口获取打开某个人的个人主页,按F12 选择XHR 然后点击图1的关注我的人,和我关注的人,在图2就可以看到header和cookie。 获取用户列表Api: https://www.zhihu.com/api/v4/...{username}/{type}?include=data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics&offset=20&limit=20username 是用户名, type 是类型, 有两种可选 [followers,followees], followers是粉丝 followees是关注改变offset的值可以获取分页 获取个人信息Api: https://www.zhihu.com/people/...user_token是用户名这个api中 返回的是html页面,在html页面中有一个scirpt标签里面的内容是json格式的用户信息,这就很方便了,直接获取键值对 对应的属性就ok。 发送请求F12查看接口,把header和cookie放进requests.get()方法中。 剩下的就很简单了,不赘述了。 总结还有很多优化的地方。比如加入中间件,来提升爬虫的稳定性。对数据进行分类,统计城市分布。

June 27, 2019 · 1 min · jiezi

三目运算符

python与c系语言相比,没有三目运算符,下面的写法可以达到三目运算符的效果。 格式:判断条件是true时的结果 if 判断条件 else 判断条件为false的结果 python:"true" if 3 > 1 else "false"C:3 > 1 ? "true" : "false";

June 25, 2019 · 1 min · jiezi

python-str-转换-json

使用Python编码和解析JsonPython内置了json包来帮助我们完成对json的操作。 针对str操作:将Python的字典结构导出到json使用json.dumps() ,将json读成Python的字典结构,使用json.loads() 。 针对对文件操作:分别使用json.load()函数和json.dump()函数。 # coding=gbkimport tracebackimport jsonfile_name = '广州市_农贸市场_1717.txt'f = open(file_name, 'r')tmp = json.load(f)print(type(tmp))data = []for i in tmp:# print(i)#测试做一下格式转换 dl = { "name":i["name"], "location_lat" : i["location"]["lat"], "location_lng" : i["location"]["lng"] } data.append(dl)print(data)with open('ceshi.txt', 'w', encoding="utf-8") as f: f.write(json.dumps(data, ensure_ascii=False)) print('---wirte success---')附上 广州市_农贸市场_1717.txt [{"name": "江南市场", "location": {"lat": 23.179127, "lng": 113.236457}, "address": "广东省广州市白云区增槎路926号", "province": "广东省", "city": "广州市", "area": "白云区", "street_id": "9fbfeef24609615cece4a59b", "detail": 1, "uid": "9fbfeef24609615cece4a59b"}, {"name": "广州番禺清河市场", "location": {"lat": 22.938501, "lng": 113.401308}, "address": "广东省广州市番禺区亚运大道94号", "province": "广东省", "city": "广州市", "area": "番禺区", "street_id": "bc57b5426b43342922f01731", "telephone": "(020)84629663", "detail": 1, "uid": "bc57b5426b43342922f01731"}]

June 4, 2019 · 1 min · jiezi

mac-python3-轻松安装教程

推荐看原文:http://tryenough.com/python_install首先要知道,mac自带一个2.7版本的python,如果你之前没装过其他版本,在终端运行 python --version 就会看到这个版本号打印出来。 你可以直接使用这个版本的python进行操作。 这里教你轻松安装python3,以及虚拟环境的配置。 安装homebrew在终端执行命令 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent...)"执行完成后,homebrew和pip等工具就自动安装好了 接下来安装python3.在终端执行命令: brew install python执行完成后可以在的系统目录: /usr/local/Cellar/python 中看到python的安装版本 注意:在 /usr/bin/ 目录中的python是系统预装的python 此时,如果你希望在终端中输入 python 直接使用的是你新安装的python3。那么需要配置一下环境变量,指定一下python只用版本就行了。如下配置: export PATH=${PATH}:/usr/local/Cellar/python/3.7.3/binalias python="/usr/local/Cellar/python/3.7.3/bin/python3"alias pip="/usr/local/Cellar/python/3.7.3/bin/pip3"推荐看原文:http://tryenough.com/python_install解释一下: 第一行指定python3全局环境变量第二行为python命令重命名第三行为pip命令重命名此时就安装好并配置好了python3 安装虚拟环境开发中不同项目使用的库不同,可以为不同的项目建立一个单独的虚拟python环境。在这个环境中安装属于这个项目的库版本。 所以虚拟环境就应运而生了。 首先安装虚拟环境和虚拟环境管理工具 pip install virtualenvpip install virtualenvwrapper注意,如果你没有像上面那样给pip重命名,你需要使用pip3安装 类似命令 pip3 install virtualenvpip3 install virtualenvwrapper接着,我们在根目录创建一个目录,用来存放我们的虚拟环境,(这个目录位置你可以自定义) 推荐看原文:http://tryenough.com/python_installmkdir ~/Pyenv然后配置一下环境变量 export WORKON_HOME=~/PyenvVIRTUALENVWRAPPER_PYTHON=/usr/local/Cellar/python/3.7.3/bin/python3source /usr/local/bin/virtualenvwrapper.sh配置好之后,就可以尝试使用 一下了。 包管理器命令: lsvirtualenv -b 查看虚拟环境 workon 切换或者进入虚拟环境 lssitepackages 查看当前环境中安装的那些包(启动虚拟环境后) deactivate 退出虚拟环境 rmvirtualenv 虚拟环境名 删除虚拟环境 推荐看原文:http://tryenough.com/python_install虚拟环境命令: virtualenv py3 创建一个叫py3的虚拟环境 我们进去虚拟环境中:cd py3/bin ...

May 13, 2019 · 1 min · jiezi

可视化工具1用matplotlib画些简单的图

环境是python3.7,工具使用的是jupyter-notebook交互式笔记本引入相关库 from pandas import DataFrame,Seriesimport matplotlib.pyplot as pltimport numpy as np%matplotlib inline # 这一行是jupyter-notebook特有的语法,其他IDE不用写画图之前的设置: plt.rcParams['font.sans-serif'] = ['SimHei'] # 修改字体为黑体,否则画出的图有中文的话就识别不出plt.rcParams['axes.unicode_minus'] = False # 设置图的X轴Y轴刻度支持负号画一张折线图: plt.figure(1,figsize=(10,4)) # 设置画布的尺寸plt.plot(np.random.random_integers(-20,20,20)) # 从-20到20之间随机取20个数plt.title('这是一条折线图') # 设置图的标题plt.xticks([0,5,10,15,20]) # 设置x轴的刻度plt.xlabel('X轴') # 设置X轴的标签plt.show() # 显示图最终画出的折现图如下: 在上面的图中再添加一条折线图: plt.figure(1,figsize=(10,4))plt.plot(np.random.random_integers(-20,20,20)) # 第一条折线图plt.plot(np.random.random_integers(-20,20,20)) # 第二条折线图plt.legend(('no1','no2')) # 这个函数标注折线图plt.title('这是一条折线图')plt.xticks([0,5,10,15,20])plt.xlabel('X轴')plt.show()plt.legend()函数只是一个开关的作用,写了就代表开启图例的标注,上述代码也等价于: plt.figure(1,figsize=(10,4))plt.plot(np.random.random_integers(-20,20,20),label='no1') # 第一条折线图plt.plot(np.random.random_integers(-20,20,20),label='no2') # 第二条折线图plt.legend() # 打开开关plt.title('这是一条折线图')plt.xticks([0,5,10,15,20])plt.xlabel('X轴')plt.show()最终效果: 修改折线图的颜色,在画图函数传入color选项即可: plt.figure(1,figsize=(10,4))plt.plot(np.random.random_integers(-20,20,20),color = 'red') # 红色plt.plot(np.random.random_integers(-20,20,20),color = 'green') # 绿色plt.legend(('no1','no2'))plt.title('这是一条折线图')plt.xticks([0,5,10,15,20])plt.xlabel('X轴')plt.show()效果:

May 5, 2019 · 1 min · jiezi

数据科学库pandas笔记3

缺失数据的处理1. 缺失数据的表现对于一些数据,可能某些值是空的,是缺失的。pandas中可以有多种处理缺失数据的方式。在pandas中,缺失数据的表现是NaN(Not a Number),可以使用isnull()函数检测出是否有数据缺失。 In [4]: data = pd.Series(['aaa','bbb',np.nan,'ddd'])In [5]: dataOut[5]:0 aaa1 bbb2 NaN3 ddddtype: objectIn [6]: data.isnull()Out[6]:0 False1 False2 True3 Falsedtype: boolisnull返回一个布尔型的对象,这些布尔值表示哪些值是缺失值NaN,该对象返回的类型和原类型一样。 处理缺失数据的方式有多种,常见为删除缺失数据与填充缺失数据。 2. 丢弃缺失数据pandas的dropna方法可以有效的删除掉缺失数据,对于Series来说,dropna方法返回一个仅含非空数据和索引值的Series: In [7]: dataOut[7]:0 aaa1 bbb2 NaN3 ddddtype: objectIn [8]: data.dropna()Out[8]:0 aaa1 bbb3 ddddtype: object对于DataFrame,dropna可以删除所有含有空值的行或列,也可以根据个人删除指定的行或列,dropna默认会删除所有含有NaN的行: In [17]: dfOut[17]: name age area0 aa 18 北京1 NaN 18 广州2 cc 20 NaNIn [18]: df.dropna()Out[18]: name age area0 aa 18 北京传入how='all',那么dropna只会删除一行全是缺失值的行: In [19]: df.loc[3]=[np.nan,np.nan,np.nan]In [20]: dfOut[20]: name age area0 aa 18.0 北京1 NaN 18.0 广州2 cc 20.0 NaN3 NaN NaN NaNIn [21]: df.dropna(how='all')Out[21]: name age area0 aa 18.0 北京1 NaN 18.0 广州2 cc 20.0 NaN如果要删除有缺失值的一列,只需要传入axis=1: ...

May 2, 2019 · 3 min · jiezi

python简单判断输入年份是否为闰年

"""闰年:能被4整除,并且不能被100整除或者能被4整除,并且又能被400整除"""while 1: this_time = int(input("请输入年份:")) #条件1 condition1 = this_time%4 == 0 and this_time%100 != 0 #条件2 condition2 = this_time%4 == 0 and this_time%400 == 0 if (condition1 or condition2): print("%d年是闰年"%(this_time)) else: print("%d年不是闰年"%(this_time))

May 2, 2019 · 1 min · jiezi

数据科学库pandas笔记2

对于pandas来说,掌握了Series和DataFrame的基本使用后,pandas还提供了很多高阶的函数与方法可以实现更加高级的功能,使用它们可以提高分析的效率,满足更多的需求。pandas高阶函数与方法依旧以一个简单的DataFrame为例: In [161]: dfOut[161]: city education top avg work_year0 上海 本科 9 8.0 3年1 广州 硕士 15 11.0 2年2 广州 本科 12 10.0 应届毕业生3 北京 本科 13 12.0 2年4 北京 本科 11 8.0 1年下面的函数或者方法操作都是以这个DataFrame对象为例。 1. 转置方法T这个方法可以实现行标签和列标签的转置,常用于矩阵运算方面。 In [161]: dfOut[161]: city education top avg work_year0 上海 本科 9 8.0 3年1 广州 硕士 15 11.0 2年2 广州 本科 12 10.0 应届毕业生3 北京 本科 13 12.0 2年4 北京 本科 11 8.0 1年In [162]: df.TOut[162]: 0 1 2 3 4city 上海 广州 广州 北京 北京education 本科 硕士 本科 本科 本科top 9 15 12 13 11avg 8 11 10 12 8work_year 3年 2年 应届毕业生 2年 1年2. 排序与排名pandas中的排序有两种,一种是对行或者列索引(sort_index)进行排序,另外一种是按值对一列即Series对象(sort_values)进行排序。 ...

May 1, 2019 · 4 min · jiezi

Canny 边缘检测及相关应用

该内容为 《学习图像局部特征检测和描述-基于OpenCV源码分析的算法与实现》《OpenCV 3 计算机视觉-Python语言实现》OpenCV官方网站的 https://docs.opencv.org/maste...的学习内容 1 Canny 边缘检测Canny 边缘检测方法是由 Canny 于1996 年提出的一种公认为效果较好的边缘检测方法。 一个好的边缘检测方法应该满足三项指标 1、低失误率,即不能漏检也不能错检2、高的位置精度,标定的边缘像素点与真正的边缘中心之间距离应该最小3、每个边缘应该由唯一的响应,即得到单像素宽度的边缘。基于此,Canny提出了判定边缘检测算子的3个准则: 1 - 信噪比准则2 - 定位精度准则3 - 单边缘响应准则Canny 算子实现过程共有4(5)个步骤: 1 - 平滑处理,使用高斯滤波器对图像进行去噪处理2 - 计算梯度3 - 非极大值抑制,即在图像边缘上使用非最大抑制NMS4 - 滞后阈值处理,即在检测到的边缘上使用双阈值去除假阳性(false positive)5 - 最后分析所有边缘及其之间的连接,以确保保留真正的边缘,同时消除不明显的边缘

April 21, 2019 · 1 min · jiezi

python精确地进行浮点数的四舍五入

做python实验时碰到这么一道题:输入三个浮点数,求它们的平均值并保留 1 位小数,对小数后第二位数进行四舍五入,最后输出结果错误示范因为涉及到四舍五入,随便搜了一下,发现了好多博客都用round(),就直接拿来用了round(1.555, 2) // 对小数后第二位数进行四舍五入但是当我测试时发现这个四舍五入有点水啊!比如:>>>round(0.5)0>>>round(1.5)2原因和想的不一样啊,然后我就去找python的官方文档,它是这么描述的:round(values, ndigits),values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice.值四舍五入到最接近的10倍幂减去ndigits;如果两个倍数相等,则四舍五入到偶数。什么意思?我尝试了几个例子才明白是怎么一回事。如果你写过大学物理的实验报告,那么你应该会记得老师讲过,直接使用四舍五入,最后的结果可能会偏高。所以需要使用四舍六入五成双的处理方法。例如对于一个小数a.bcd,需要精确到小数点后两位,那么就要看小数点后第三位:如果d小于5,直接舍去如果d大于5,直接进位如果d等于5:d后面没有数据,且c为偶数,那么不进位,保留cd后面没有数据,且c为奇数,那么进位,c变成(c + 1)如果d后面还有非0数字,例如实际上小数为a.bcdef,此时一定要进位,c变成(c + 1)所以,把round()当成四舍五入并不是十分准确的一处小陷井但是,到这里并没有完,当我又换了一组数据测试时,发现了问题:>>>round(0.645,2) # 按照上述舍入规则,应该是0.64,但结果却是0.65这里就涉及到python的浮点数存储了,python采用IEEE754标准存储浮点数的,所以当我输入0.645后,底层存储的其实是0011111111100100101000111101011100001010001111010111000010100100,也即十进制的0.645000000000000017763568394002504646778106689453125,离0.65更近。正确姿势从上可知,round()对浮点数四舍五入存在舍入规则和浮点数存储的问题对于浮点数运算,python提供了Decimal(小数)模块来让小数的运算更贴近我们人正常计算的习惯。import decimal# 修改舍入方式为四舍五入decimal.getcontext().rounding = “ROUND_HALF_UP”# 使用字符串来储存小数不会有精度误差,Decimal可以正确处理这种方法表示的数字decimal.Decimal(“0.645”).quantize(decimal.Decimal(“0.00”))或者为了避免浮点数储存导致精度损失,干脆全部都用字符串来储存小数,如下:from decimal import Decimala = Decimal(‘0.655’) + Decimal(‘0.345’)b = 0.655 + 0.345# a = 1.000# b = 1.0总结关于浮点数运算和四舍五入的问题,以前在学习C语言时就遇到了,但当时并不清楚浮点数的存储和运算,也没有找到一个合适的解决方法,这学期学习了计算机组成,才把这个问题算是比较清楚地给解决了。现在越来越能感觉到python语言的大火,好多别的行业的人也通过python转到了IT行业,但本身水平不高,缺乏计算机底层的知识,又在网上瞎写博客误导别人,这次吃了垃圾博客的亏,以后搜索时还是尽量用英文+谷歌吧!

April 20, 2019 · 1 min · jiezi

3. 领养小樱花

本文为 Aiello 的 《给女朋友的Python旅行》系列文章,转载请征得本人同意。接上篇文章 第一个 Python 小程序????从今天开始,我们会领养一只叫 小樱花 的猫咪????,她会陪伴你整个 Python 旅程????起个名字还是用上一节课的那个 main.py 文件,将下面的代码拷贝粘贴进去name=“小樱花"print(name)像这样点击 Debug -> Start Debugging 或者键盘快捷键 F5 就可以开始运行啦。在下面,我们的程序输出了猫咪????的名字上面代码中,name=“小樱花” 中的 name 叫做变量,可以理解为数学中的 x,我们可以让 name 等于任何我们想让它等于的数据,name=“123"name="❤️"name=“Chouchou"在上面的代码中,“123” “❤️” “Chouchou” 等,用英文的双引号"包起来的,我们叫做字符串,因为他们就是一串文字。字符串是 Python 中数据的一种类型,同样的,python 中还有很多其他的数据类型,比如 数字(123 0.1 等)、布尔值(True 或者 False) 等在后面,我们用 print 这个 函数 把 name 的数据输出到屏幕上,括号中就是要让 print 这个函数要输出的数据,叫做 参数print(“123”)print("❤️”)print(“Chouchou”)在上面的例子中 name=“小樱花” 是将 小樱花 这个名字保存在了 name 这个变量中,然后通过 print(name) 把 name 中保存的数据展示到屏幕上,它的效果和 print(“小樱花”) 是一样的添加个性化的描述name=“小樱花"print(“我的名字是:” + name)通过 + 号,我们可以把数据合并在一起,比如把 “我的名字是:” 这一串文字和 name 这个变量合并在一起,python 会自动将 name 转换成它所对应的数据,也就是 “小樱花” 然后把这些文字拼接起来,运行后是这个效果:添加更多信息给小樱花增加年龄属性name=“小樱花"age=1print(“我的名字是:” + name)print(age)在这里,年龄数据的值等于 1,这个 1 我们没有用 " 号包起来了,因为它是一个数字类型的数据,可以直接使用,不用像文字一样要用 " 包起来。可能你想要在年龄前加一些文字,比如像这样:name=“小樱花"age=1print(“我的名字是:” + name)print(“我的年龄是:” + age)但是在运行后,你会发现,好像和平时有什么不同,程序运行出错了,上面的错误提示告诉我们 “can only concatenate str (not “int”) to str”,意思是,只能用 + 号连接两个 str(也就是字符串) 类型的数据,不能把 int(数字) 类型的数据和 str 类型的数据进行连接这个时候,我们可以点击上方的停止符号,关闭此次运行的程序那既然 str(string)类型的数据只能和 str 类型的数据合并,那我们可以将 int(integer) 类型的数据转化成 str 类型的数据,使用 str 这个函数,我们就可以做到这一点name=“小樱花"age=1print(“我的名字是:” + name)print(“我的年龄是:” + str(age))其中 str 叫做函数名,它就像一台机器,我放进去 数字类型的数据,它就可以产出 str 类型的数据了,然后 str 类型的 “我的年龄是:” 就可以和 str 类型的数据相合并了,像下面这样 ...

April 17, 2019 · 1 min · jiezi

阿里云centos7.2下安装chrome浏览器+webdriver+selenium及常见设置-傻瓜教程

Linux版本:阿里云CentOS Linux release 7.2.1511 (Core) root用户下python版本python3.6,python3安装方法https://www.cnblogs.com/FZfangzheng/p/7588944.html 测试时间:2019-04-161.安装chrome浏览器1.1 创建yum源文件cd /etc/yum.repo.d/touch google-chrome.repo1.2 输入yum源信息[google-chrome]name=google-chromebaseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearchenabled=1gpgcheck=1gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub1.3 安装google chromeyum -y install google-chrome-stable –nogpgcheck2.安装chromedriver及seleniumyum install chromedriverpip install selenium默认安装路径:chromedriver: /usr/bin/chromedriver3.修改配置来执行代码,及常见错误处理3.1测试demo#!/usr/bin/env python# -- coding=UTF-8 --#测试代码import timefrom selenium import webdriverdef test(): chromeOptions = webdriver.ChromeOptions() chromeOptions.add_argument(’–headless’) #浏览器无窗口加载 chromeOptions.add_argument(’–disable-gpu’) #不开启GPU加速 """ 解决报错: selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally (unknown error: DevToolsActivePort file doesn’t exist) """ chromeOptions.add_argument(’–disable-dev-shm-usage’) #禁止 chromeOptions.add_argument(’–no-sandbox’)#以根用户打身份运行Chrome,使用-no-sandbox标记重新运行Chrome #其它设置(可选): #chromeOptions.add_argument(’–hide-scrollbars’) #隐藏滚动条, 应对一些特殊页面 #chromeOptions.add_argument(‘blink-settings=imagesEnabled=false’) #不加载图片, 提升速度 #chromeOptions.add_argument(“user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36”) #伪装其它版本浏览器,有时可以解决代码在不同环境上的兼容问题,或者爬虫cookie有效性保持一致需要设置此参数 #创建driver对象 #chrome_options=chromeOptions加载设置 #executable_path="/usr/bin/chromedriver"指定webdriver路径(可选) driver = webdriver.Chrome(chrome_options=chromeOptions,executable_path="/usr/bin/chromedriver") try: driver.get(“http://www.baidu.com”) time.sleep(3) print(driver.page_source) except Exception as e: print(e) finally: driver.quit()if name == ‘main’: test()4.参考资料https://www.cnblogs.com/ianduin/p/8727333.html https://www.cnblogs.com/baijing1/p/9751399.html https://www.cnblogs.com/z-x-y/p/9507467.html ...

April 16, 2019 · 1 min · jiezi

2. 第一个 Python 小程序

本文为 Aiello 的 《给女朋友的Python旅行》系列文章,转载请征得本人同意。接上篇文章 简单的准备工作????现在我们有了完整的开发环境,我们就要开始写一个简单的 Python 小程序啦认识 VS Code 这个宇宙最强 IDE (Integrated development environment)打开 Visual Studio Code 简称 VS Code,然后我们需要在电脑上创建一个文件夹,用来保存我们的程序,我这里是在桌面上创建了一个名为 python 的文件夹然后在 VS Code 中,选择 File -> Open folder… 选择我们刚才创建的文件夹,点击确定打开后,界面大概就长这样啦 (如果你想换个颜色,可以点击 File -> Preferences -> Color Theme 然后用键盘的上下键,来切换不同的显示样式,比如白色主题)我们把光标移动到 1 区域,就会看见箭头所示的图标,点击可以新建文件我们就新建一个文件,命名为 main.py然后点击回车,我们就新建了我们的第一个 Python 文件!VS Code 识别到了我们正在写 Python 程序(.py 结尾的文件),就给我推荐插件了,安装了这些工具我们就能够更好的进行开发了(比如能自动给我们提示代码怎么写),点击 “install”正在安装插件了插件装好后,他又提示我们有一些工具没有装了,点击安装然后就是一些在科幻片中客串的画面出现了????屏幕上文字乱跑现在我们来写一些 Python 代码,在右上角的编辑区域内,敲下面的文字print(‘Hello Jessica❤️’)然后按 crtl + s 保存文件 (macos 按 ⌘ + S 保存)当成功保存的时候,箭头所指的这个小白点就会消失,所以我们看到有小白点,就代表这个文件还没有保存最后我们要运行它啦选择 Debug -> Start Debugging 或者键盘快捷键 F5 即可开始运行 Python 了最后我们在右下角的程序输出界面看到,程序顺利地输出了我们想要的文字 Hello Jessica❤️好了,我们已经完整地把开发一个程序所需要的步骤都进行了一遍,现在可以简单介绍一下 VS Code 的界面了左侧五个按钮,分别是:文件管理,可以管理你的代码文件查询,在所有的代码中查找文字版本控制(以后会讲)调试(传说中的找Bug)插件管理,安装一些好用的工具,来帮助你更好地完成工作这五个按钮会一直存在的,所以你可以随时地点点点他们任意一个,进入对应的功能,完全不怕玩坏哈哈哈所有区域的宽度、高度都是可以通过拖拽边缘部分进行改变大小的Python 代码试试运行一下下面的代码,看会是什么结果print(’\n’.join([’’.join([(‘LoveU’[(x-y)%4]if((x0.05)**2+(y0.1)**2-1)**3-(x0.05)*2(y0.1)**3<=0 else’ ‘)for x in range(-30,30)])for y in range(15,-15,-1)]))下节课开始,我们就要开始学习 Python 的基础知识了,每节课都会由一个非常有趣的例子开始❤️ ...

April 15, 2019 · 1 min · jiezi

1. 简单的准备工作????

本文为 Aiello 的 《给女朋友的Python旅行》系列文章,转载请征得本人同意。Python 是一门有趣的编程语言,现在不论是自动化工具,还是大数据、人工智能都可以看到 Python 的身影,应用非常广泛,所以我准备教国杰儿学大蟒蛇 Python❤️。希望在她之后的学习中,能够有所帮助????今天是 Python 的第一课,主要是讲一下,如何能够在我们的电脑上使用 Python????其实,总的就只有 两个步骤:1. 安装 Python2. 安装一个文本编辑器1. 安装 Python要在电脑上编辑文档,我们就要安装 Office 软件,同样我们电脑上要运行 Python 程序,我们就需要安装 Python 的运行环境在这个网址 https://www.python.org/downlo… 我们下载适合我们电脑的软件(一般默认的就行)下载完成后,双击下载的软件即可开始安装在弹出的权限申请框中,点击同意(或者“是”)即可如果出现下方选项,点击所示的位置,然后在弹出的权限框中选择同意就可以了最后点击右下角的 close 按钮,关闭窗口我们就安装好了 Python 工作环境(比 Office 快多了吧????)2. 安装编辑器有了能运行 Python 程序的环境,我们现在需要写点 Python 程序了,用什么写呢?那就是代码编辑器,我们现在就安装一个代码编辑器在这个网站 https://code.visualstudio.com/ 点击这里,他会自动根据你的电脑来下载合适的软件等下载完成,双击安装一路接受协议并且点击下一步这里勾选后,会在桌面上创建一个快捷方式,便于打开也是不一会儿就安装好了,可以点击完成,软件会自动打开以后我们主要就使用这个名为 Visual Studio Code 的软件进行我们的 Python 之旅啦下一步我们会学习如何写一个简单的 Python 程序

April 15, 2019 · 1 min · jiezi

django富文本编辑器

最近一段时间都在学django,现在的网站基本都要使用到富文本编辑器,今天就记录下使用django的管理后台的一个富文本编辑器的第三方库 DjangoUeditor使用方法1.安装方法一:将github整个源码包下载回家,在命令行运行:python setup.py install方法二:使用pip工具在命令行运行(推荐):pip install DjangoUeditor<!– more –>2.在 settings.py的INSTALL_APPS里面增加DjangoUeditor appINSTALLED_APPS = [ … ‘DjangoUeditor’]3.配置urls 在urls.py 里添加路由# 富文本path(‘ueditor/’, include(‘DjangoUeditor.urls’)),4.在 modal 使用# 引入 UEditorFieldfrom DjangoUeditor.models import UEditorField# 使用class Demo(model.Model): detail = UEditorField(verbose_name=u’详情’, width=600, height=300, imagePath=“courses/ueditor/”, filePath=“courses/ueditor/”, default=’’)5.在template里的HTML 文件里面,把这个字段渲染出来{% autoescape off %}{{ course.detail }}{% endautoescape %}6.在 xadmin 中使用#在该模块的 xadmin.py 中加上style_fields = {“detail”: “ueditor”}问题我是在虚拟环境里起的项目,这样安装好之后,报了一个TypeError: render() got an unexpected keyword argument ‘renderer’解决需要修改虚拟环境下的:boundfield.py文件: .virtualenvs/虚拟环境文件/lib/python3.X/site-packages/django/forms/boundfield.py89 return widget.render(90 name=self.html_initial_name if only_initial else self.html_name,91 value=self.value(),92 attrs=attrs,93 # renderer=self.form.renderer,(93行处注 释掉,就能正常运行了)94 ) 示例blog: http://blog.beastxw.wang ...

April 10, 2019 · 1 min · jiezi

机器学习 | 树回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~运行结果代码from numpy import #使用二元切分法——每次将数据集切成两份#如果数据的某特征值等于切分所要求的值,#那么这些数据就进入树的左子树,反之则# 进入右子树def loadDataSet(fileName): dataMat=[] fr=open(fileName) for line in fr.readlines(): curLine=line.strip().split(’\t’) #将每行映射成浮点数 fltLine=list(map(float,curLine)) dataMat.append(fltLine) #将文件中的所有数据都保存在同一个矩阵中 return dataMat#参数:数据集,待切分的特征,该特征的某个值def binSplitDataSet(dataSet,feature,value): #将数据集合切分得到两个子集并返回 mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:] mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:] return mat0,mat1#建立叶结点的函数#当chooseBestSplit函数决定不再对数据集进行切分时,将调用该regLeaf函数#来得到叶节点的模型。在回归树种,该模型其实就是目标变量的均值def regLeaf(dataSet): return mean(dataSet[:,-1])#计算误差的函数——这里计算的是总方差def regErr(dataSet): #均方差函数var数据集中样本的个数=总方差 return var(dataSet[:,-1]) * shape(dataSet)[0]#给定某个误差计算方法,该函数会找到数据集上最佳的二元切割方式#(他遍历所有的特征及可能的取值来找到使误差最小化的切分阈值)#另外,该函数还要确定什么时候停止切分,一旦停止切分就会生成一个叶节点#errType为平方误差的总值(总方差)def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): #用户指定的参数,用于控制函数停止时机 #tolS为误差下降值,tolN为切分的最少样本数 tolS = ops[0]; tolN = ops[1] #如果所有值相等则退出 if len(set(dataSet[:,-1].T.tolist()[0])) == 1: #找不到一个“好”的二元切分,返回None并同时调用leafType来生成叶节点 return None, leafType(dataSet) m,n = shape(dataSet) S = errType(dataSet) bestS = inf; bestIndex = 0; bestValue = 0 for featIndex in range(n-1): for splitVal in set((dataSet[:,featIndex].T.A.tolist())[0]): mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal) if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue newS = errType(mat0) + errType(mat1) if newS < bestS: bestIndex = featIndex bestValue = splitVal bestS = newS #如果误差减少不大则退出 if (S - bestS) < tolS: return None, leafType(dataSet) mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue) #如果切分出的数据集很小则退出 if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): return None, leafType(dataSet) #找到了一个“好”的切分方式,返回特征编号和切分特征值 #找到了最佳的切分方式:切分后能达到最低误差的切分 return bestIndex,bestValue#构建树的函数#dataSet为数据集#leafType为建立叶结点的函数,errType为误差计算函数#ops是一个包含书构建所需其他参数的元组def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): #chooseBestSplit为切分函数 #若满足停止条件chooseBestSplit将返回None和某类模型的值 #如果构建的是回归树,该模型是一个常数,如果是模型树,其 #模型是一个线性方程(回归树假设叶节点是常数值) #若不满足停止条件,chooseBestSplit将创建一个新的python #字典,并将数据集分成两份,在这两份数据集上分别继续递归调 #用createTree函数 feat,val=chooseBestSplit(dataSet,leafType,errType,ops) #满足停止条件时返回叶节点 if feat==None: return val retTree={} retTree[‘spInd’]=feat retTree[‘spVal’]=val #将数据集按照待分特征和该特征的某个值进行二分操作 lSet,rSet=binSplitDataSet(dataSet,feat,val) #创建左右子树 retTree[’left’]=createTree(lSet,leafType,errType,ops) retTree[‘right’]=createTree(rSet,leafType,errType,ops) return retTreedef drawFigure1(): # import matplotlib.pyplot as plt # myDat=loadDataSet(’ex00.txt’) # myMat=mat(myDat) # createTree(myMat) # plt.plot(myMat[:,0],myMat[:,1],‘ro’) # plt.show() import matplotlib.pyplot as plt myDat=loadDataSet(’ex0.txt’) myMat=mat(myDat) createTree(myMat) plt.plot(myMat[:,1],myMat[:,2],‘ro’) plt.show()def main(): drawFigure1() # myDat=loadDataSet(’ex00.txt’) # myMat=mat(myDat) # myTree=createTree(myMat) # print(myTree) #建立一个主对角线元素全为1的矩阵 #testMat=mat(eye(4)) #print(testMat) #要分割的特征位于第一列 #按照0.5去划分 #mat0,mat1=binSplitDataSet(testMat,0,0.5) # print(mat0) # print(mat1)if name==’main’: main()``` ...

March 30, 2019 · 2 min · jiezi

机器学习 | 预测数值型数据:回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~线性回归局部加权线性回归代码from numpy import import matplotlib.pyplot as plt#标准回归函数和数据导入函数#默认文本的最后一行为目标值#第一列为偏移量,假定为常数1.0#第二列为x1,也就是图中的横坐标def loadDataSet(fileName): numFeat=len(open(fileName).readline().split(’\t’))-1 dataMat=[] labelMat=[] fr=open(fileName) for line in fr.readlines(): lineArr=[] curLine=line.strip().split(’\t’) for i in range(numFeat): lineArr.append(float(curLine[i])) dataMat.append(lineArr) labelMat.append(float(curLine[-1])) return dataMat,labelMat#计算最佳拟合曲线#.T标识矩阵的转置def standRegres(xArr,yArr): xMat=mat(xArr) #矩阵转置,变程行向量 yMat=mat(yArr).T #判断xTx的转置与xTx相乘是否为0 xTx=xMat.TxMat #若为0,那么计算逆矩阵的时候会出错 if linalg.det(xTx)==0.0: print(“this matrix is singular,cannot do inverse”) return #计算ws #.I返回矩阵的逆 ws=xTx.I*(xMat.TyMat) return ws #绘制数据集散点图和最佳拟合直线图def drawFigure(): xArr,yArr=loadDataSet(’ex0.txt’) ws=standRegres(xArr,yArr) xMat=mat(xArr) yMat=mat(yArr) fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0]) xCopy=xMat.copy() xCopy.sort(0) yHat=xCopyws ax.plot(xCopy[:,1],yHat) plt.show() #局部加权线性回归#给待预测的点附近的每个点赋予一定的权重#在这个子集上基于最小均方差来进行普通的回归#使用的核为高斯核#最终构建了一个只含对角元素的权重矩阵w,并且x与x(i)越近,#w(i,i)将会越大#局部加权线性回归函数def lwlr(testPoint,xArr,yArr,k=1.0): xMat=mat(xArr) yMat=mat(yArr).T m=shape(xMat)[0] #创建对角矩阵 #权重矩阵是一个方阵,阶数为样本点的个数 #该矩阵为每个样本点初始化了一个权重 weights=mat(eye((m))) #遍历数据集,计算每个样本点对应的权重值 #随着样本点与待预测点距离的递增,权重将以指数级衰减 #参数k控制衰减的速度 #权重值大小以指数级衰减 for j in range(m): diffMat=testPoint-xMat[j,:] weights[j,j]=exp(diffMatdiffMat.T/(-2.0k**2)) xTx=xMat.T*(weightsxMat) if linalg.det(xTx)==0.0: print(“This matrix is singular,cannot do inverse”) return #得到回归系数 ws=xTx.I(xMat.T*(weightsyMat)) return testPointwsdef lwlrTest(testArr,xArr,yArr,k=1.0): m=shape(testArr)[0] yHat=zeros(m) #为数据集中的每个点调用lwlr() for i in range(m): yHat[i]=lwlr(testArr[i],xArr,yArr,k) return yHatdef drawfigure2(): xArr,yArr=loadDataSet(’ex0.txt’) #print(yArr[0]) yHat0=lwlr(xArr[0],xArr,yArr,1.0) #print(yHat0) yHat=lwlrTest(xArr,xArr,yArr,0.01) xMat=mat(xArr) strInd=xMat[:,1].argsort(0) xSort=xMat[strInd][:,0,:] fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xSort[:,1],yHat[strInd]) ax.scatter(xMat[:,1].flatten().A[0],mat(yArr).T.flatten().A[0],s=2,c=‘red’) plt.show() def main(): drawfigure2() #drawFigure() #xArr,yArr=loadDataSet(’ex0.txt’) #ws=standRegres(xArr,yArr) #xMat=mat(xArr) #yMat=mat(yArr) #计算预测值yHat和真实值y的匹配程度——计算两个序列的相关程度 #yHat=xMat*ws #arr=corrcoef(yHat.T,yMat) #yHat与yMat的相关系数为0.98 #[[1. 0.98647356] #[0.98647356 1. ]] #print(arr) #[[1.0, 0.067732], [1.0, 0.42781],…] #print(xArr) #[3.176513, 3.816464,…] #print(yArr) #[[3.00774324] #[1.69532264]] #Haty=wx[0]*x0+ws[1]*x1 #print(ws)if name==’main’: main() ...

March 28, 2019 · 1 min · jiezi

机器学习 | Logistic回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~Logistic回归进行分类分类效果Logistic回归预测病马的死亡率预测结果全部代码from numpy import import matplotlib.pyplot as plt#使用梯度上升法找到最佳参数#使用梯度上升法找到最佳回归系数,#也就是拟合Logistic回归模型的最佳参数#Logistic归回梯度上升优化算法#加载文件def loadDataSet(): dataMat=[];labelMat=[] #打开文本文件 fr=open(’testSet.txt’) #逐行读取 for line in fr.readlines(): lineArr=line.strip().split() #为了方便计算,将x0设为1,后面的x1,x2是文本中每行的前两个值 dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #文本中每行的第三个值为数据对应的标签 labelMat.append(int(lineArr[2])) return dataMat,labelMat #sigmiod函数def sigmoid(inX): return 1.0/(1+exp(-inX)) #梯度上升算法#第一个参数是一个2维的Numpy数组#每列表示不同的特征#每行表示每个训练样本#我们采用100个样本,包含两个x1,x2特征#再加上第0维特征x0,所以dataMatIn是一个100X3的矩阵#第二个参数是类别标签,是一个1X100的行向量def gradAscent(dataMatIn,classLabels): dataMatrix=mat(dataMatIn) #将行向量转置为列向量 labelMat=mat(classLabels).transpose() #得到矩阵的大小 m,n=shape(dataMatrix) #向目标移动的步长 alpha=0.001 #迭代次数 maxCycles=500 weights=ones((n,1)) #在for循环结束之后,将返回训练好的回归系数 for k in range(maxCycles): #注:此处是矩阵相乘 #h是一个列向量,元素的个数等于样本的个数 h=sigmoid(dataMatrixweights) #真实类别与预测类别的差别 error=(labelMat-h) #按照该差别的方向调整回归系数 weights=weights+alphadataMatrix.transpose()error #返回回归系数——确定了不同类别数据之间的分割线 return weights #画出决策边界#画出数据集和Logistic回归最佳拟合直线的函数 #X1表示一个特征,X2表示另一个特征def plotBestFit(weights): #得到数据集与标签 dataMat,labelMat=loadDataSet() dataArr = array(dataMat) n = shape(dataArr)[0] xcord1 = []; ycord1 = [] xcord2 = []; ycord2 = [] #对数据集进行分类 for i in range(n): if int(labelMat[i])== 1: xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2]) else: xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2]) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcord1, ycord1, s=30, c=‘red’, marker=’s’) ax.scatter(xcord2, ycord2, s=30, c=‘green’) x = arange(-3.0, 3.0, 0.1) #根据gradAscent得到的回归系数绘制分割线 y = (-weights[0]-weights[1]x)/weights[2] #print(x) #print(y) ax.plot(x, y) plt.xlabel(‘X1’); plt.ylabel(‘X2’); plt.show() #梯度上升方法在每次更新回归系数时都需要遍历整个数据集#改进方法:一次仅使用一个样本点来更新回归系数——随机梯度上升算法#由于可以在新样本到来时对分类器进行增量式更新,因此随机梯度上升#算法是一个在线学习算法#与“在线学习”相对应,一次数里所有数据被称作“批处理”#随机梯度上升算法def stocGradAscent0(dataMatrix,classLabels): #得到矩阵的大小 m,n=shape(dataMatrix) #向目标移动的步长 alpha=0.01 weights=ones(n) for i in range(m): #h为向量 h=sigmoid(sum(dataMatrix[i]weights)) #error为向量 error=classLabels[i]-h weights=weights+alphaerrordataMatrix[i] return weights #由于经过测试,多次迭代后,X0,X1收敛速度较小#且存在一些小的周期性的波动,因此及逆行改进#改进随机梯度上升算法#第三个参数为迭代次数def stocGradAscent1(dataMatrix,classLabels,numIter=150): m,n=shape(dataMatrix) weights=ones(n) for j in range(numIter): dataIndex=list(range(m)) for i in range(m): #改进1:alpha[向目标移动的步长]会随着迭代的次数不断减小 #可以缓解数据波动或高频波动, alpha=4/(1.0+j+i)+0.01 #通过随机选取样本来更新回归系数 #可以减少周期性的波动 randIndex=int(random.uniform(0,len(dataIndex))) h=sigmoid(sum(dataMatrix[randIndex]weights)) error=classLabels[randIndex]-h weights=weights+alphaerrordataMatrix[randIndex] del(dataIndex[randIndex]) return weights #Logistic回归预测病马的死亡率#对于缺失数据,我们选择用0来替换#因为这样不会影响系数weights的值#对于标签已经丢失的,我们将这条数据丢弃#使用Logistic回归进行分类的主要思路:#把测试集上每个特征向量乘最优方法得到的回归系数#再将该乘积结果求和,最后输入Sigmoid函数中即可,#若对应的sigmoid值>0.5预测类别标签为1,否则为0#Logistic回归分类函数def classifyVector(inX,weights): #以回归系数和特征向量作为输入来计算对应的Sigmoid值 prob=sigmoid(sum(inXweights)) if prob>0.5:return 1.0 else:return 0.0#打开测试集和训练集,并对数据进行格式化处理 def colicTest(): frTrain=open(‘horseColicTraining.txt’) frTest=open(‘horseColicTest.txt’) trainingSet=[] trainingLabels=[] #遍历每一行 for line in frTrain.readlines(): currLine=line.strip().split(’\t’) lineArr=[] #遍历每一列 for i in range(21): lineArr.append(float(currLine[i])) trainingSet.append(lineArr) #最后一列为类别标签 trainingLabels.append(float(currLine[21])) #计算回归系数向量 trainWeights=stocGradAscent1(array(trainingSet),trainingLabels,500) errorCount=0 numTestVec=0.0 for line in frTest.readlines(): numTestVec+=1.0 currLine=line.strip().split(’\t’) lineArr=[] for i in range(21): lineArr.append(float(currLine[i])) #对测试集进行分类,并查看结果是否正确 if int(classifyVector(array(lineArr),trainWeights))!=int(currLine[21]): errorCount+=1 #计算错误率 errorRate=(float(errorCount)/numTestVec) print(“the error rate of this test is: %f”%errorRate) return errorRate#调用colicTest函数10次,并且结果的平均值 def multiTest(): numTests=10 errorSum=0.0 for k in range(numTests): errorSum+=colicTest() print(“after %d iterations the average error rate is: %f”%(numTests,errorSum/float(numTests))) def main(): #dataArr,labelMat=loadDataSet() #weights=gradAscent(dataArr,labelMat) #print(weights) #plotBestFit(weights.getA()) #weights=stocGradAscent0(array(dataArr),labelMat) #weights=stocGradAscent1(array(dataArr),labelMat) #plotBestFit(weights) multiTest() if name==’main’: main() ...

March 27, 2019 · 2 min · jiezi

机器学习 | 朴素贝叶斯

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~用朴素贝叶斯进行词汇分类代码from numpy import #词表到向量的转换#创建实验样本,返回的是进行词条切分后的文档集合,#还有一个类别标签——侮辱性的or非侮辱性的def loadDataSet(): postingList=[[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’], [‘maybe’, ’not’, ’take’, ‘him’, ’to’, ‘dog’, ‘park’, ‘stupid’], [‘my’, ‘dalmation’, ‘is’, ‘so’, ‘cute’, ‘I’, ’love’, ‘him’], [‘stop’, ‘posting’, ‘stupid’, ‘worthless’, ‘garbage’], [‘mr’, ’licks’, ‘ate’, ‘my’, ‘steak’, ‘how’, ’to’, ‘stop’, ‘him’], [‘quit’, ‘buying’, ‘worthless’, ‘dog’, ‘food’, ‘stupid’]] #1 代表侮辱性文字 0代表正常言论 classVec = [0,1,0,1,0,1] return postingList,classVec #创建一个包含在所有文档中出现的不重复的词的列表 def createVocabList(dataSet): vocabSet=set([]) #document:[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’] for document in dataSet: #求并集 vocabSet=vocabSet|set(document) #print(vocabSet) return list(vocabSet) #参数为词汇表以及某个文档,输出的是文档向量#输出的向量的每一个元素为1或0,表示词汇表中#的单词在输入文档中是否出现def setOfWords2Vec(vocabList,inputSet): #创建一个所含元素都为0的向量 returnVec=[0]len(vocabList) #遍历文档中的所有单词,如果出现了词汇表中的单词, #则将输出文档的对应值设为1 for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)]=1 else: print(“the word: %s is not in my Vocabulary!"%word) return returnVec #输入的参数:文档矩阵trainMatrix#由每篇文档类别标签构成的向量trainCategory#朴素贝叶斯分类器训练函数#trainMatrix:每个词向量中的词,在词汇表中出现的就是1#trainMatrix:[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], #[0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0],#[1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], #[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0], #[0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], #[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0]]#该词向量中带有侮辱性的词的就是1#trainCategory:[0, 1, 0, 1, 0, 1]def trainNBO(trainMatrix,trainCategory): #一共有几个词向量 numTrainDocs=len(trainMatrix) #词汇表的长度 numWords=len(trainMatrix[0]) #3/6 表示6个词向量中,3个带侮辱词 pAbusive=sum(trainCategory)/float(numTrainDocs) #初始化概率 p0Num=ones(numWords) p1Num=ones(numWords) p0Denom=2.0;p1Denom=2.0 #遍历训练集trainMatrix中的所有文档 #一旦某个词在某一文档中出现 #该文档的总词数加1 #两个类别都要进行同样的处理 #i:012345 for i in range(numTrainDocs): #该词向量带侮辱 if trainCategory[i]==1: #向量相加 p1Num+=trainMatrix[i] p1Denom+=sum(trainMatrix[i]) else: p0Num+=trainMatrix[i] p0Denom+=sum(trainMatrix[i]) #每个元素除以该类别的总词数 p1Vect=log(p1Num/p1Denom) p0Vect=log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive #朴素贝叶斯分类函数def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #元素相乘 p1=sum(vec2Classifyp1Vec)+log(pClass1) p0=sum(vec2Classifyp0Vec)+log(1.0-pClass1) if p1>p0: return 1 else: return 0 def testingNB(): listOPosts,listClasses=loadDataSet() myVocabList=createVocabList(listOPosts) trainMat=[] #使用词向量填充trainMat列表 for postinDoc in listOPosts: Vec01=setOfWords2Vec(myVocabList,postinDoc) trainMat.append(Vec01) p0V,p1V,pAb=trainNBO(trainMat,listClasses) #测试集 testEntry=[’love’,‘my’,‘dalmation’] thisDoc=array(setOfWords2Vec(myVocabList,testEntry)) #print(thisDoc) print(testEntry,’ classified as: ‘,classifyNB(thisDoc,p0V,p1V,pAb)) testEntry=[‘stupid’,‘garbage’] thisDoc=array(setOfWords2Vec(myVocabList,testEntry)) #print(thisDoc) print(testEntry,’ classified as: ‘,classifyNB(thisDoc,p0V,p1V,pAb)) def main(): testingNB() #创建数据 #listOPosts,listClasses=loadDataSet() #print(listOPosts) #构建一个包含所有词的列表 #myVocabList=createVocabList(listOPosts) #print(myVocabList) #returnVec=setOfWords2Vec(myVocabList,listOPosts[0]) #print(returnVec) #trainMat=[] #使用词向量填充trainMat列表 #for postinDoc in listOPosts: #传入词汇表 以及每一行词向量 #返回的是一个与词汇表同样size的向量 #1表示这个词在词向量中出现过 #Vec01=setOfWords2Vec(myVocabList,postinDoc) #print(Vec01) #将01list填充trainMat #trainMat.append(Vec01) #print(trainMat) #print(listClasses) #p0V,p1V,pAB=trainNBO(trainMat,listClasses) #print(p0V) #print(p1V) #print(pAB) if name==’main’: main() ...

March 25, 2019 · 2 min · jiezi

py入门学习-判断、循环、dict和set

条件判断num = input(‘随便输入一个数字:’)try num = int(num)except ValueError as e: print(‘你输入的不是数字’)if num > 0: print(‘你输入的数字大于0’)elif num < 0: print(‘你输入的数字小于0’)else: print(‘你输入的数字等于0’)循环#for x in list 将序列的每个元素代入变量xlist = [1,2,3]for item in range(101): print(item)#while 条件为true 就一直循环num = 0flag = Truewhile flag: if num == 2: flag = False else: num = num +1#flag = False num =2#break 强制结束循环num = 0flag = Truewhile flag: if num == 2: flag = False else: num = num +1 break#flag = Ture num =1#continue 结束本轮循环执行下一次num = 0flag = Truewhile num < 5: num = num +1 if num == 3: continue print(num)# 1 2 4 5dict词典和set#dict 有点像json对象obj = { ’name’: ‘小明’, ‘age’: 18}#dict方法## get get(key,key不存在时你想反回的值)obj.get(’name’,None)## pop pop(key) 删除key以及值if ‘age’ in obj : obj.pop(‘age’)## clear 删除所有元素obj.clear()## copy 浅复制 以及直接赋值的区别obj1 = { ’name’: ‘小明’, ‘age’: 18}obj2 = obj1.copy() #只会深拷贝父级对象 子对象还是浅拷贝obj3 = obj1 #随obj1 元素变化obj1[’names’] = ‘大明’print(obj2,obj3) # {’name’: ‘小明’, ‘age’: 18} {’name’: ‘小明’, ‘age’: 18, ’names’: ‘大明’}、##items 返回可遍历的键 值 元组数组(tuple)item = obj.items() #dict_items([(’name’, 1)])##keys 返回所有的键obj = { ’name’: ‘小明’, ‘dict’: { ‘index’: 1 }}obj.keys() #dict_keys([’name’]),不返回二维以上的##values 返回所有的值 只返回一维obj.values() #dict_values([‘小明’, {‘index’: 1}])##update 更新词典(dict),两个dict的合并obj1 = { ‘sex’: ‘男’}obj.update(obj1) #{’name’: ‘小明’, ‘dict’: {‘index’: 1}, ‘sex’: ‘男’}##popitem 随机删除一对键值obj.popitem() #(‘sex’, ‘男’) 返回删除的键值对类型为元祖 tuple#set#和dict类似 但是没有值 只存储key,并且key不能为重复 输入重复也无效果sets = set([1, 2, 3]) #{1, 2, 3}## 方法## add(key)sets.add(4) #{1, 2, 3, 4}## remove(key)sets.remove(1) #{2, 3, 4}实践代码 ...

March 12, 2019 · 1 min · jiezi

scala常用操作

scala常用操作版本信息python3.7pyspark2.4.0from pyspark import SQLContext,SparkContext,SparkConfconf = SparkConf()sc = SparkContext(conf=conf)sqlContext = SQLContext(sc)#加载csv文件data = sqlContext.read.format(“csv”).option(“header”,“true”).load(“union_order_user”)#按字段降序排序sorted=data.sort(“created_at”,ascending = False)#展示前100条记录 默认展示20条sorted.show(100)

March 9, 2019 · 1 min · jiezi

Flask出现Error code 400, message Bad request syntax异常

有一个小坑,所以记录下。请求api是出现Error code 400, message Bad request syntax,然后后面有一串乱码其实这个问题最大的原因就是请求时用的https,然后flask服务没有配置ssl证书,所有报错了。换成http请求即可。

February 25, 2019 · 1 min · jiezi

LeetCode 319. Bulb Switcher

DescriptionThere are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it’s off or turning off if it’s on). For the i-th round, you toggle every i bulb. For the n-th round, you only toggle the last bulb. Find how many bulbs are on after n rounds.Example:Input: 3Output: 1 Explanation: At first, the three bulbs are [off, off, off].After first round, the three bulbs are [on, on, on].After second round, the three bulbs are [on, off, on].After third round, the three bulbs are [on, off, off]. So you should return 1, because there is only one bulb is on.描述初始时有 n 个灯泡关闭。 第 1 轮,你打开所有的灯泡。 第 2 轮,每两个灯泡你关闭一次。 第 3 轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭)。第 i 轮,每 i 个灯泡切换一次开关。 对于第 n 轮,你只切换最后一个灯泡的开关。 找出 n 轮后有多少个亮着的灯泡。示例:输入: 3输出: 1 解释: 初始时, 灯泡状态 [关闭, 关闭, 关闭].第一轮后, 灯泡状态 [开启, 开启, 开启].第二轮后, 灯泡状态 [开启, 关闭, 开启].第三轮后, 灯泡状态 [开启, 关闭, 关闭]. 你应该返回 1,因为只有一个灯泡还亮着。思路数学题,对给定的数字开平方向下取整即是答案。暴力求解(会超时),但是通过暴力解法可以发现规律。我们声明一个长度为 n 的数组,数组初始值为 0 。然后我们按照题目要求对其进行改变状态的操作,0 表示关,1 表示开。我们通过这个会发现如果给定的 n 为前三个数(13)会有 1 盏灯亮着,如果给定的 n 为接下来的 5 个数 (48),会有 2 盏灯亮着,接下来的 7 个数(915)会有3 盏灯两者,我们称给定的所有可能的 n 中,最后剩下相同的灯亮着的情况的 n 为一组,于是可以发现每组 n 的个数是一个首项为 3 公差为 2 的等差数列。于是有了第一个解法:我们不断的从 n 中减去,3,5,7 … (n 小于零就停止),能减少多少次就有多少盏灯亮着。我们可以发现 13:1;48:2;915:3,16~25:4,不难发现我们对 n 开放取整就可以得到答案,关于严格的数学证明请参考 这里-solution-with-explanation) 。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-23 18:46:36# @Last Modified by: 何睿# @Last Modified time: 2019-02-23 19:46:07class Solution: def bulbSwitch(self, n: int) -> int: return int(n**0.5) def bulbSwitch2(self, n: int) -> int: count, i = 0, 3 # 首项为3,公差为 2 的等差数列 # n 为这些数字的和 while n > 0: # 每次从 n 中去掉一项 n -= i i += 2 # 记录去掉的次数 count += 1 # 次数就是剩下的晾着的灯泡个数 return count def bulbSwitch3(self, n: int) -> int: # 最直观的思路,用一个数组表示灯泡的开关情况,0 表示关,1 表示开 # !!! 此方法会超时 bulbs = [0 for i in range(n)] for i in range(n): j = i # 每轮调整 i 整数倍的位置 while j < n: bulbs[j] ^= 1 j += i + 1 # 统计最后剩下的 1 的个数 return bulbs.count(1)源代码文件在 这里 。©本文首发于 何睿的博客 ,欢迎转载,转载需保留 文章来源 ,作者信息和本声明. ...

February 24, 2019 · 2 min · jiezi

LeetCode 318. Maximum Product of Word Lengths

DescriptionGiven a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.Example 1:Input: [“abcw”,“baz”,“foo”,“bar”,“xtfn”,“abcdef”]Output: 16 Explanation: The two words can be “abcw”, “xtfn”.Example 2:Input: [“a”,“ab”,“abc”,“d”,“cd”,“bcd”,“abcd”]Output: 4 Explanation: The two words can be “ab”, “cd”.Example 3:Input: [“a”,“aa”,“aaa”,“aaaa”]Output: 0 Explanation: No such pair of words.描述给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。示例 1:输入: [“abcw”,“baz”,“foo”,“bar”,“xtfn”,“abcdef”]输出: 16 解释: 这两个单词为 “abcw”, “xtfn”。示例 2:输入: [“a”,“ab”,“abc”,“d”,“cd”,“bcd”,“abcd”]输出: 4 解释: 这两个单词为 “ab”, “cd”。示例 3:输入: [“a”,“aa”,“aaa”,“aaaa”]输出: 0 解释: 不存在这样的两个单词。思路基本思路很简单:对给定的单词两两组合,如果这两个单词没有相同的字符,记下者两个单词长度值的乘积,返回最大值。如何判断两个单词是否使用了相同的单词:我们使用位运算,整形有 32 位,字符只有 26 个。我们让二进制的数第一位表示 a ,第二位表示 b … 第 26 位表示 z 。如果某个字母在给定的单词中出现了,我们记字母对应位置的二进制位 1 。如果两个单词没有使用相同的字母,那么这两个单词对应的二进制按位与一定为 0 ,因为两个单词没有使用相同的字母,所以二进制中的 1 都是错开的。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-23 13:14:24# @Last Modified by: 何睿# @Last Modified time: 2019-02-23 14:24:48import itertoolsclass Solution: def maxProduct(self, words) -> int: # bits 是字典,键为单词 word 对应的二进制码,值为一个二进制码对应的最长单词 # 最长单词:单词 a,aa,aaa,aaaa,对应的二进制码都是 0b1,为了获得最大的乘积 # 我们取最长的单词 aaaa,所以 0b1 对应 4 bits = {} for word in words: # 获取单词单词对应的 二进制码,有点类似哈希,但是不完全相同 bit = self.getBit(word) # 建立键值对,这样可以避免多次 len(word) # 值为最长单词的长度 bits[bit] = max(bits.get(bit, 0), len(word)) # 对一个列表的所有元素进行两两组合 # 也可以用循环,如 maxProduct2 中示例 # 但是在 python 中 itertools.combinations 更快 com = itertools.combinations(bits.keys(), r=2) # 对所有组合中单词没有重复的求乘积,这里也可以写成循环的形式 # 但是在 python 中列表解析式的执行速度更快 return max([bits[x] * bits[y] for x, y in com if x & y == 0] or [0]) def maxProduct2(self, words) -> int: res = 0 bits = [self.getBit(word) for word in words] for i in range(len(words)): for j in range(i + 1, len(words)): if bits[i] & bits[j] == 0: res = max(res, len(words[i]) * len(words[j])) return res def getBit(self, word): bit = 0 # 按位或 # 字母 a 对一二进制第 1 位,b 对应第 2 位 … z 对应 第 26 位 for char in word: bit = bit | (1 << (ord(char) - 97)) return bit源代码文件在 这里 。©本文首发于 何睿的博客 ,欢迎转载,转载需保留 文章来源 ,作者信息和本声明. ...

February 23, 2019 · 2 min · jiezi

LeetCode 316. Remove Duplicate Letters

DescriptionGiven a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.Example 1:Input: “bcabc"Output: “abc"Example 2:Input: “cbacdcbc"Output: “acdb"描述给定一个仅包含小写字母的字符串,去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。示例 1:输入: “bcabc"输出: “abc"示例 2:输入: “cbacdcbc"输出: “acdb"思路字典序最小:对于两个字符串 S 和 T,如果 S1 < T1,则 字符串 S 的字典序更小。比如第一个例子字符串 “bcabc” 去掉重复后可能的结果有:1.bca 2. bac 3. cab 4.abc 「注意只能从前往后遍历取出字符」。对于 1 和 2,由于 b == b,c > a,所以 2 的字典序比1小,同理 2 的字典序比 3 小,4 的字典序比 2 小,所以最终答案是 4。我们使用 stack 和 字典这两种数据结构。我们用一个字典记录每个字符出现的次数。核心思路是:假设 stack 中记录了给定的 S 中前 i 个字符的结果,那么针对第 i+1 个字符,如果第 i+1 个字符还没有出现在 stack 中,如果:1.第 i+1 个字符比栈顶元素小并且栈顶元素在第 i+1 个元素之后还会出现,那么 第 i+1 个元素应该在 stack 栈顶元素的前面,于是我们弹出 stack 栈顶元素,并用第 i+1 个元素和现在的栈顶元素比较,如果此时第 i+1 个元素仍比栈顶元素小并且此时的栈顶元素在第 i+1 个元素之后仍会出现,我们继续弹出栈顶元素 …2.第 i+1 个字符比栈顶元素小但是栈顶元素在这之后不会出现了,我们把当前元素追加到栈顶。3.如果当前元素本身就比栈顶元素大,我们把当前元素追加到栈顶。如上,我们需要知道一个元素在之后会不会出现:我们借助字典来实现,字典的键为字符,值为字符在给定的字符串中出现的次数,如果一个字符对应的值大于零,说明这个字符还会出现,如果等于零则不会出现。每次访问一个字符的时候,我们首先让字典中该字符对应的值自减一次,表示已经访问了一次。我们还需要知道一个字符是否已经出现过了在 stack 中,也就是有没有被处理过,我们用 Hastset 来实现,每访问到一个字符,我们都把它加入到 set 中,在第 1 种情况种,如果一个元素从栈顶被弹出了,我们也从 set 中移除这个元素,表示这个元素还没有被处理。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-22 14:27:31# @Last Modified by: 何睿# @Last Modified time: 2019-02-22 15:38:39import collectionsclass Solution: def removeDuplicateLetters(self, s: ‘str’) -> ‘str’: # stack 用于存储已经获取的结果 # visited 表示当前的字符已经遍历过 stack, visited = [], set() # times 是一个字典,键为字符,值为字符出现过的次数 times = collections.Counter(s) for item in s: # 让字典 times 中记录的对应次数减少一次 times[item] -= 1 # 如果 item 还没有遍历过,即 item 没有出现在结果中 # visited 和 stack 里面的字符内容是一样的 # 只不过我们用stack 是为了从栈顶开始删除 # 用 visited 可以在 O(1) 时间复杂度内判断一个元素是否被遍历过并且在 O(1) 内删除一个元素 if item not in visited: # 如果当前元素比栈顶元素小并且栈顶元素在当前元素后面还会出现 # 那么当前元素应该带栈顶元素的前面 # 我们弹出栈顶元素,在 visited 中删除栈顶元素的记录 while stack and item < stack[-1] and times[stack[-1]] != 0: visited.remove(stack.pop()) # 此时有下列三种情况 # 1. 栈已经空了 # 2. 当前元素大于栈顶元素 # 3. 当前元素小于栈顶元素但是栈顶元素在当前元素后面不再出现 # 我们将当前元素压入栈顶,在 visited 元组中记录当前元素已经被访问过 stack.append(item) visited.add(item) # 注意题目要求返回字符串 return ‘’.join(stack)源代码文件在 这里。©本文首发于 何睿的博客,欢迎转载,转载需保留文章来源,作者信息和本声明. ...

February 22, 2019 · 2 min · jiezi

Python基本数据类型之列表

学习Python的列表类型需要了解和掌握什么是列表、列表的可变性、列表的访问、列表的增删改查等操作~1.了解列表list1 = [‘abc’, 123, {1, 2, 3},[2,3]]Python中的列表有点类似与C语言中的数组的概念;python中的列表是可变的,且列表内部由元素组成,元素可以是任意对象,也就是说列表的数据项不需要具有相同的类型,比如整形、浮点型、字符串、其他类的对象、实例等都可以作为列表的元素。2.列表的定义下面是4种定义列表的方法:lst = list() #定义一个空列表lst = [] #定义一个空列表lst = [1,2,3.5,‘abc’] #元素可以是任意数据类型lst = list(range(10)) #定义一个从0到9的列表3.列表的可变性 a = 1 print(id(a)) #输出:262330544 a = 2 print(id(a)) #输出:262330560列表的可变与不可变性,是对内存地址而言的;被初始化的列表,可以通过列表的API接口对列表的元素进行增删改查;4.列表的访问列表是有序集合,所以列表可以通过索引访问 lst = [1,2,3,4,5] #初始化一个列表lst通过索引访问列表里面的值,列表名[索引大小](索引是从0开始计算的); print(lst[1]) #输出2通过index方法获取值对应的索引,列表名.index(值); print(lst.index(4)) #输出 3通过count方法获取值在列表中出现的次数,列表名.count(值); print(lst.count(2)) #输出1通过len()函数获取列表的长度,len(列表名);print(len(lst)) #输出5#### 5.列表的插入lst = [1,2,3,4,5] #初始化一个列表* append方法:在列表的末尾插入数据;lst.append(5) print(lst) 输出[1, 2, 3, 4, 5, 5]* insert方法:在列表的任意位置插入数据;lst.insert(0, 100) print(lst) 输出[100, 1, 2, 3, 4, 5]* extend方法:添加可迭代对象的元素;lst.extend(range(10)) print(lst) 输出[1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]* +:叠加两个列表元素;lst_new = lst + [1,2,3] print(lst_new) 输出 [1, 2, 3, 4, 5, 1, 2, 3]* *:复制列表元素;lst_new = lst * 3 print(lst_new) 输出 [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]#### 6.列表的删除lst = [1,2,3,4,5] #初始化一个列表* remove方法:移除从左自右的第一个匹配的元素;lst.remove(3) print(lst) 输出[1, 2, 4, 5]* pop方法:带值的情况下,移除指定索引的元素,在不带值的情况下,移除最后一个元素;lst.pop(2) print(lst) 输出[1, 2, 4, 5]lst.pop() print(lst) 输出[1, 2, 3, 4]* clear方法:清空整个列表;lst.clear() print(lst) 输出[]#### 7.列表的排序lst = [1,2,3,4,5] #初始化一个列表* reverse方法:将列表中的元素反向;lst.reverse() print(lst) 输出[5, 4, 3, 2, 1]* sort方法:给元素排序,(注:reverse控制指定是正向还是反向,默认是False,代表升序);lst.sort() print(lst) 输出[1, 2, 3, 4, 5]lst.sort(reverse=True) print(lst) 输出[5, 4, 3, 2, 1]* in 关键字:判断元素是否在列表里面;if 1 in lst:print(‘yes’) 输出yes#### 8.列表的复制lst = [1,[1,2,3],3,4,5]lst_new = lst.copy() print(lst_new) #输出[1, [1, 2, 3], 3, 4, 5]lst1 = 100 print(lst_new) #输出[1, [1, 100, 3], 3, 4, 5]* 浅拷贝:如果改变原始列表的值,copy得到的新的列表的值会跟着改变;import copy #导入一个copy模块 lst = [1,[1,2,3],3,4,5]lst_new = copy.deepcopy(lst) print(lst_new) #输出[1, [1, 2, 3], 3, 4, 5]lst1 = 100 print(lst_new) #输出[1, [1, 2, 3], 3, 4, 5]* 深拷贝:注意需要导入一个copy模块,深拷贝和前拷贝相反,如果改变原始列表的值,copy得到的新的列表的值并不会跟着改变;#### 9.random模块import random #导入random模块 print(random.randint(1,100)) #输出1到99中任意一个整数 print(random.choice([‘x’,3,5,7])) #输出这四个元素中的任意一个 print(random.randrange(1,100,2)) #输出1到99中的任意一个属于 2n+1 的值lst = [1,2,3,4,5] random.shuffle(lst) #将lst列表打乱 print(lst)* 需要导入一个random模块;* randint:取区间中任意一个值,注意区间是闭区间;* choice:从给出列表中随机取一个值;* randrange:左边是闭区间,右边是开区间;* shuffle:将列表打乱; ...

February 19, 2019 · 2 min · jiezi

LeetCode 313. Super Ugly Number

DescriptionWrite a program to find the nth super ugly number.Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k.Example:Input: n = 12, primes = [2,7,13,19]Output: 32 Explanation: [1,2,4,7,8,13,14,16,19,26,28,32] is the sequence of the first 12 super ugly numbers given primes = [2,7,13,19] of size 4.Note:1 is a super ugly number for any given primes.The given numbers in primes are in ascending order.0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.The nth super ugly number is guaranteed to fit in a 32-bit signed integer.描述编写一段程序来查找第 n 个超级丑数。超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数。示例:输入: n = 12, primes = [2,7,13,19]输出: 32 解释: 给定长度为 4 的质数列表 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。说明:1 是任何给定 primes 的超级丑数。给定 primes 中的数字以升序排列。0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000 。第 n 个超级丑数确保在 32 位有符整数范围内。思路这道题和第 264 题 Ugly Number II 做法类似。我们使用动态规划。状态:我们用 index 用于记录 primes 中每个质数上一次产生丑数的有效位置,并用一个数组 uglynum 记录产生的丑数。比如 index[2] = 7, 表示质数 primes[2] 上一次产生的质数在 uglynum 中的索引为 7 ,即产生的丑数为 uglynum[7]。初始值:index 所有值初始化 0,ugly 第一个值初始化为1。状态转移方程:获取下一个丑数:我们用 index 中记录的上一次质数产生的丑数在 uglynum 中的位置获得对应的丑数 uglynum[index[i]],并用对应的质数 primes[i] 与 uglynum[index[i]] 相乘作为下一次可能的丑数,所有的丑数用一个临时数组 _next 存储。我们取所有数中的最小值作为下个丑数。更新 index 数组:如果 uglynext == _next[i],我们让 index[i] 自增一次。结果:丑数数组的最后一个值。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-19 15:35:20# @Last Modified by: 何睿# @Last Modified time: 2019-02-19 16:11:26class Solution: def nthSuperUglyNumber(self, n: ‘int’, primes: ‘List[int]’) -> ‘int’: """ :type n: int :rtype: int """ # 处理特殊情况,如果n为1或者primes为空,返回1 if n < 2 or not primes: return 1 # 声明一个数组,用于存储获取的丑数 uglynum = [1] # 辅助变量,primes的个数,当前生成的丑数的个数 num, count = len(primes), 1 # index数组用于存储primes中每个数上一次产生有效数的下一个位置 index = [0 for _ in range(num)] while count < n: # 动态规划,用primes中的每个数从上一次产生有效位置的地方产生下一个数 _next = [primes[i] * uglynum[index[i]] for i in range(num)] # 下一个丑数是产生的丑数中最小的数 uglynext = min(_next) # 更新索引值 for i in range(num): if uglynext == _next[i]: index[i] += 1 uglynum.append(uglynext) count += 1 # 返回最后一个丑数 return uglynum[-1]源代码文件在 这里。©本文首发于 何睿的博客,欢迎转载,转载需保留文章来源,作者信息和本声明. ...

February 19, 2019 · 2 min · jiezi

LeetCode 312. Burst Balloons

DescriptionGiven n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] nums[i] nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.Find the maximum coins you can collect by bursting the balloons wisely.Note:You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100Example:Input: [3,1,5,8]Output: 167 Explanation: nums = [3,1,5,8] –> [3,5,8] –> [3,8] –> [8] –> [] coins = 315 + 358 + 138 + 181 = 167描述有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] nums[i] nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。求所能获得硬币的最大数量。说明:你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100示例:输入: [3,1,5,8]输出: 167 解释: nums = [3,1,5,8] –> [3,5,8] –> [3,8] –> [8] –> [] coins = 315 + 358 + 138 + 181 = 167思路这道题使用动态规划。状态:我们声明一个二维数组 matrix[len(nums)][len(nums)],matrix[i][j] 表示戳数组 nums[i] (包括) 到数组 nums[j]的气球可以获得的最大值。初始状态:matrix 的每一个值都为0。状态转移方程:从第 left 个位置到第 rigth 个位置,我们以 left 到 right 中的任意一个位置 k 为例,假设最后一个戳 k 气球(其他所有气球已经戳爆了)则我们可以获得的硬币为 num[left:k] + nums[left-1] * nums[k] * nums[right+1] + nums[k:right]num[left:k]:戳破 k 位置左边所有气球的可以获得的硬币。nums[left-1] * nums[k] * nums[right+1]:戳破当前位置可以获得的气球,由于 num[left:right] 中只有 k 为位置没有被戳破,所以 k 位置左边的位置为 nums[left-1],如果越界则置为1,右边的有效值为 nums[right+1] ,如果越界则置为1。nums[k:right]:戳破 k 位右边所有气球的可以获得的硬币。结果:matrix[0][len(nums)-1]。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-18 14:52:28# @Last Modified by: 何睿# @Last Modified time: 2019-02-18 15:44:09class Solution: def maxCoins(self, nums: ‘List[int]’) -> ‘int’: # 如果数组为空,我们返回0 if not nums: return 0 # 声明一个二维矩阵,matrix[i][j]表示戳num[i]到num[j]的气球可以获得的最大值 matrix = [[0] * len(nums) for _ in range(len(nums))] # left表示起点,right表示中点,count表示right-left的值 # 辅助变量初始化为0 left, right, count = 0, 0, 0 for count in range(0, len(nums)): # 每一趟循环,left都从最左边开始 left = 0 # right表示所有可能的中点 for right in range(count, len(nums)): # 临时变量用于记录最大值 _max = 0 # 从left到right中,我们以每一个位置为最后一个戳气球的位置 for j in range(left, right + 1): # 当前位置左边可以获得的最大值 _left = matrix[left][j - 1] if j - 1 >= left else 0 # 当前位置右边可以获得的最大值 _right = matrix[j + 1][right] if j + 1 <= right else 0 # 当前串的左边界的左边一个值 leftnum = nums[left - 1] if left - 1 >= 0 else 1 # 当前串的有边界的右边一个值 rightnum = nums[right + 1] if right + 1 < len(nums) else 1 # 以当前位置为嘴后一个戳气球的位置,可以获得的硬币个数 product = _left + nums[j] * leftnum * rightnum + _right _max = max(_max, product) # 更新最大值 matrix[left][right] = _max left += 1 # matrix[0][len(nums) - 1]表示从0到len(nums)可以获得的最多的硬币个数 return matrix[0][len(nums) - 1]源代码文件在 这里。©本文首发于 何睿的博客,欢迎转载,转载需保留文章来源,作者信息和本声明. ...

February 18, 2019 · 2 min · jiezi

LeetCode 310. Minimum Height Trees

DescriptionFor an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.FormatThe graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels).You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.Example 1 :Input: n = 4, edges = [[1, 0], [1, 2], [1, 3]] 0 | 1 / \ 2 3 Output: [1]Example 2 :Input: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] 0 1 2 \ | / 3 | 4 | 5 Output: [3, 4]Note:According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.描述对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。注意:该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。示例 1:输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]] 0 | 1 / \ 2 3 输出: [1]示例 2:输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] 0 1 2 \ | / 3 | 4 | 5 输出: [3, 4]说明:根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。树的高度是指根节点和叶子节点之间最长向下路径上边的数量。思路最小高度树的根节点是图中最长路径的中间节点.我们用一个 List[set()] 的结构存储每个节点可以访问到的其他节点。一般情况下应该使用字典,以节点为键,能够遍历到的节点组成的哈希set为键,但由于题中的节点是从0开始的数字,我们可以用 List 来代替,索引就是键。最长路径的中间节点最多会有两个:最长路径有奇数个节点,则中间节点有 1 个;最长路径有偶数个节点,则中间节点有 2 个。基本思路是:找到所有的叶子节点,去掉所有叶子节点,找到新的所有叶子节点,去掉所有叶子节点 … 直到剩下的节点个数小于等于2个。# -- coding: utf-8 --# @Author: 何睿# @Create Date: 2019-02-17 13:46:09# @Last Modified by: 何睿# @Last Modified time: 2019-02-17 14:15:30class Solution: def findMinHeightTrees(self, n: ‘int’,edges: ‘List[List[int]]’) -> ‘List[int]’: # 如果只有一个节点,直接返回当前节点 if n == 1: return [0] # 路径:记录每个节点可以访问到的所有节点 type:list[set()] # 更一般的情况是利用字典实现,利用节点作为键,节点能够走到的所有节点 # 组成的set作为值,但是题中得节点为从0开始的数值,因此可以用list代替字典 paths = [set() for _ in range(n)] # 找到每个节点可以走到的下一个节点 for node1, node2 in edges: paths[node1].add(node2) paths[node2].add(node1) # 找到所有的叶子节点 leaves = [node for node in range(n) if len(paths[node]) == 1] # root用于记录剩下的节点 roots = n while roots > 2: # 更新剩下的节点个数 roots -= len(leaves) # 新的叶子节点 newleaves = [] for node in leaves: # 获取叶节点的父节点 parent = paths[node].pop() # 从叶节点的父节点中删除当前节点 paths[parent].remove(node) # 如果当前节点的父节点只能访问一个节点,则添加到新叶节点中 if len(paths[parent]) == 1: newleaves.append(parent) leaves = newleaves return leaves源代码文件在这里.©本文首发于何睿的博客,欢迎转载,转载需保留文章来源,作者信息和本声明. ...

February 17, 2019 · 3 min · jiezi

weekly 2019-02-15

我开始学习Python了,这样我可以用它作为后端语言来学,也可以用来刷Leetcode,学爬虫等等这周我学习了:Python基础语法BeautiuilSoup Request库学习记录在这里 前期语法还不熟,慢慢来,有空就刷刷题

February 15, 2019 · 1 min · jiezi

Python微型异步爬虫框架

AmipyPython微型异步爬虫框架(A micro asynchronous Python website crawler framework)基于Python 3.5 + 的异步async-await 框架,搭建一个模块化的微型异步爬虫。可以根据需求控制异步队列的长度和延迟时间等。配置了可以去重的布隆过滤器,网页内容正文过滤等,完全自主配置使用。GitHub地址:源码适用环境windows 7 +Python 3.5 +安装直接使用pip安装即可:pip install amipy基础命令1.查看当前路径下的可用命令,在DOS命令行下输入:>amipy会出现命令帮助界面。2.创建一个新的项目,在DOS命令行下输入:>amipy cproject myproject会在当前路径下创建一个Amipy爬虫项目myproject。如果想要创建在指定目录下,可以加上附加参数,-d,如:> amipy cproject myproject -d D:\somefolder项目myproject便会在路径D:somefolder下创建。项目的目录结构应该如下:–myproject |-spiders | |-init.py |-init.py |-settings.py其中:settings.py 为整个项目的配置文件,可以为整个项目下的爬虫安装共有的中间件,控制整个项目的请求并发数,设置日志级别、文件路径等。3.进入项目路径,创建一个新的爬虫,在DOS命令行下输入:>amipy cspider myspider此时在项目myproject目录下的spiders文件夹中会创建一个爬虫目录myspider,此时的项目结构为:–myproject |-spiders | |-init.py | |-myspider | | |-init.py | | |-cookies.info | | |-item.py | | |-settings.py | | |-site_record.info | | |-spider.py | | |-url_record.info |-init.py |-settings.py |-log.log其中:位于myspider文件夹下的settings.py为爬虫myspider的配置文件,该配置只对当前爬虫有效。可以对该爬虫的布隆过滤器进行配置,安装中间件等。cookies.info 为爬虫的请求cookie保存文件,该爬虫爬过的所有网站的cookie会保存进该文件。可以通过爬虫配置文件settings.py进行路径加载和保存。site_record.info 为爬虫爬取过的网站的布隆过滤器记录文件,方便下次爬取的时候加载,会把爬取过的网站自动去掉。防止重复爬取。url_record.info 为该爬虫发出的请求url+headers+method+数据的去重后集合,爬虫结束运行时,如果配置保存去重url集合。下次爬取时加载该文件可以自动过滤爬取过的所有url+headers+method+数据。item.py 为ORM的MongoDB数据集合对象,对应的类属性可以映射到数据库集合中的字段,类名为数据表名。spider.py 为当前爬虫的主要文件,自己编写爬取逻辑,提取规则和数据保存脚本等。4.运行项目下的所有爬虫,进入项目路径,在DOS命令行下输入:>amipy runproject则该项目下的所有爬虫会开始运行,如果不想运行某个爬虫,只需要加上参数 -e,如:>amipy runproject -e No1spider No2spider则名为“No1spider”、“No2spider”的爬虫均不会运行。5.运行指定的爬虫,进入项目路径,在DOS命令行下输入:>amipy runspider myspider01 则名为“myspider01”的爬虫便会被启动。可以加上多个爬虫名称,用空格隔开即可。6.列出当前项目下的所有爬虫信息。在DOS命令行下输入:>amipy list便会将当前项目下的所有爬虫信息列出。使用Amipy爬虫编写流程编写自己的爬虫。【假设你已经安装前面"基础命令"创建了一个项目,并且创建了一个爬虫名为myspider】只需要进入myspider文件夹,按照需求修改当前爬虫的配置settings.py 以及数据存储需要用到的表模型item.py编写,编辑文件spider.py,加入爬取规则逻辑等。Url类对象Url类对象是一个规则匹配类,它提供了许多种模式的url规则匹配。比如:from amipy import Url# 表示匹配到正则模式’http://www.170mv.com/song.‘的所有链接Url(re=‘http://www.170mv.com/song.’)# 表示匹配到正则模式’http://www.170mv.com/song.‘的所有链接其回调函数为’getmp3’Url(re=‘http://www.170mv.com/song/.’,callback=‘getmp3’)# 表示匹配到地址为http协议,且路径为‘/novel/chapter1’,参数number=2的所有链接Url(scheme=‘http’,path=’/novel/chapter1’,params=‘number=2’)# 表示匹配到域名为www.baidu.com的所有链接,为该链接请求设置代理为'127.0.0.1:1080’Url(domain=‘www.baidu.com’,proxy=‘127.0.0.1:1080’)# 表示匹配到域名为www.baidu.com的所有链接,直接扔掉这些链接。Url(domain=‘www.baidu.com’,drop=True)Url类应用的还在于黑白名单属性中,如在爬虫类中的属性:whitelist = [ Url(re=‘http://www.170mv.com/song.’), Url(re=‘http..sycdn.kuwo.cn.’),]blacklist = [ Url(re=‘http://www.170mv.com/song.’), Url(re=‘http..sycdn.kuwo.cn.’),] 表示爬虫请求的url黑白名单匹配规则。必要属性打开spider.py ,可以看到有两个默认的必要属性:name 爬虫的唯一标识,项目下不能有该属性重名的爬虫。urls 起始链接种子,爬虫开始的url列表这两个属性是必须的。回调函数整个项目的主要实现在于回调函数的使用,利用异步请求得到响应后马上调用其请求绑定的回调函数来实现爬虫的异步爬取。请求后响应的回调函数(类方法)有:parse 返回状态200,请求正常响应正常,可以编写正常的规则提取、数据保存等。error 状态码非200,出现异常状态码,编写错误处理逻辑等。exception 请求出现异常,异常自定义处理。数据存储Amipy目前只支持MongoDB数据库,默认的数据库设置在爬虫配置文件settings.py中。对于爬取的数据进行保存,默认只使用MongoDB进行数据存储(后续可以自己扩展编写ORM)。只需要打开item.py,修改其中的示例类,原先为:from amipy.BaseClass.orm import Model,Fieldclass DataItemName(Model): …修改其内容为:from amipy.BaseClass.orm import Model,Fieldclass MyTableName(Model): ID = Field(‘索引’) content = Field(‘内容’)则类名 MyTableName为保存在指定数据库中的数据集合名称,ID为列对象,名称为“索引”,以此类推,content也为列对象,名称为“内容”。可以按照自己的需求进行添加删减列。数据的保存只需要在回调函数中对对应的列对象进行赋值,而后调用ORM对象的save函数即可。比如在spider.py的爬虫类中的成功回调函数parse中保存爬取到的数据: … def parse(self,response): self.item.ID = 200 self.item.content = ‘这是内容’ self.item.save() …则 数据集合 MyTableName中会自动保存一行数据:列“索引”为200,列“内容”为“这是内容”的数据行。引用orm数据模型对象只需要调用爬虫类的item属性,如上面示例中的self.item即是。获取其数据库对象可以使用:self.item.db来获得当前爬虫连接的MongoDB数据库对象。可以通过self.item.db.save()self.item.db.delete()self.item.db.update()…等api来实现数据库操作。事件循环loopAmipy爬虫的异步请求基于python3的协程async框架,所以项目全程只有一个事件循环运行,如果需要添加更多的爬虫请求,可以通过回调函数传进事件循环,加入请求队列。具体做法便是通过在爬虫类的回调函数中使用send函数来传递请求Request对象:import amipyfrom amipy import Request,sendclass MySpider(amipy.Spider): … def parse(self,response): … # 加入新的爬虫请求 url = ‘http://www.170mv.com/download/' send(Request(self,url)) …可以在项目配置文件settings.py中设置整个项目最大的协程并发数CONCURRENCY,以及协程请求的延时等。Telnet连接Amipy爬虫内置一个服务线程,可以通过Telnet进行连接来查看操作当前项目的爬虫,在启动爬虫后,可以通过新开一个DOS命令窗口,输入:>telnet 127.0.0.1 2232进行Telnet连接至项目服务线程,可以使用的命令有: show spiders show all running spiders and their conditions. list list a general situation of all spiders. echo echo a running spider and its attributes. pause pause a running spider by a give name. stop stop a running/paused spider by a give name. close close a spider by a give name. restart restart a stopped spider by a give name. resume resume a paused spider by a give name. quit quit the Spider-Client. help show all the available commands usage.举例,假设当前爬虫唯一标识名称为lianjia,则可以通过:$amipy> pause lianjia来暂停爬虫lianjia的爬取进度,在爬虫将当前请求队列清空后会一直暂停,直到收到Telnet端发出的其他命令。恢复爬虫使用:$amipy> resume lianjia查看当前项目下所有爬虫:$amipy> list详细查看则使用:$amipy> show spiders开启关闭Telnet在项目的配置文件settings.py中设置SPIDER_SERVER_ENABLE。例子1. 使用Amipy创建链家网爬虫(LianJiaSpider)爬虫目的:爬取链家网上北京当前最新的租房信息,包含“价格”,“房屋基本信息”、“配套设施”、“房源描述”、“联系经纪人”、“地址和交通”存入MongoDB数据库中创建项目进入到D:LianJia路径,创建Amipy项目LJproject:D:\LianJia> amipy cproject LJproject创建爬虫进入到项目路径D:LianJiaLJproject,创建Amipy爬虫lianjia:D:\LianJia\LJproject> amipy cspider lianjia编写数据库模型打开D:LianJiaLJprojectspidersLianjiaitem.py,编写数据保存模型:#coding:utf-8from amipy.BaseClass.orm import Model,Fieldclass LianJiaRenting(Model): price = Field(‘价格’) infos = Field(‘房屋基本信息’) facility = Field(‘配套设施’) desc = Field(‘房源描述’) agent = Field(‘联系经纪人’) addr = Field(‘地址与交通’)设置数据库连接打开 D:LianJiaLJprojectspidersLianjiasettings.py,找到MongoDB数据库连接设置,进行设置:# MongoDB settings for data saving.DATABASE_SETTINGS = { ‘host’:‘127.0.0.1’, ‘port’:27017, ‘user’:’’, ‘password’:’’, ‘database’:‘LianJiaDB’,}要先确保系统安装好MongoDB数据库并已经开启了服务。编写爬虫脚本打开 D:LianJiaLJprojectspidersLianjiaspider.py,编写爬虫采集脚本:import amipy,refrom amipy import send,Request,Urlfrom bs4 import BeautifulSoup as bs class LianjiaSpider(amipy.Spider): name = ’lianjia’ # 设置爬取初始链接 urls = [‘https://bj.lianjia.com/zufang/’] # 设置爬虫白名单,只允许爬取匹配的链接 whitelist = [ Url(re=‘https://bj.lianjia.com/zufang/.*’), ] # 自定义的属性 host =‘https://bj.lianjia.com’ page = 1 # 请求成功回调函数 def parse(self,response): soup = bs(response.text(),’lxml’) item_list = soup(‘div’,class_=‘content__list–item’) for i in item_list: # 获取详情页链接 并发送至爬虫请求队列 url = self.host+i.a[‘href’] send(Request(self,url,callback=self.details)) # 添加下一页 totalpage = soup(‘div’,class_=‘content__pg’)[0][‘data-totalpage’] if self.page>=int(totalpage): return self.page +=1 send(Request(self,self.host+’/zufang/pg{}/’.format(self.page))) def details(self,response): infos = {} agent = {} facility = [] soup = bs(response.text(),’lxml’) infos_li = soup(‘div’,class_=‘content__article__info’)[0].ul(’li’) facility_li = soup(‘ul’,class_=‘content__article__info2’)0 agent_ul = soup(‘ul’,id=‘agentList’)[0] addr_li = soup(‘div’,id=‘around’)[0].ul.li desc_li = soup(‘div’,id=‘desc’)[0].li desc_li.div.extract() desc = desc_li.p[‘data-desc’] if desc_li.p else ’’ for i in infos_li: text = i.text if ‘:’ in text: infos.update({text.split(’:’)[0]:text.split(’:’)[1]}) for i in facility_li[1:]: if ‘no’ not in i[‘class’][-2]: facility.append(i.text) for div in agent_ul(‘div’,class=‘desc’): name = div.a.text phone = div(‘div’,class_=‘phone’)[0].text agent[name]=phone # 数据模型对应并保存 self.item.desc = desc self.item.addr = re.sub(r’[\r\n ]’,’’,addr_li.text) if addr_li else ’’ self.item.price = soup(‘p’,class_=‘content__aside–title’)[0].text self.item.infos = infos self.item.agent = agent self.item.facility = facility self.item.save()如果在爬虫配置文件settings.py中设置遵守目标网站机器人协议可能会被禁止采集,可以自行关闭设置。另外,开启网页内容相似过滤BLOOMFILTER_HTML_ON可能会使爬取的结果数较少,爬虫只会采集相似度不同的网页内容的链接,如果需要大批量采集,而网页正文较少的,可以关闭这个设置。代码比较粗糙,但可以知道Amipy爬虫基本的实现流程。运行爬虫在项目根路径下,输入:D:\LianJia\LJproject> amipy runspider查看数据库进入MongoDB数据库:可以看到在数据库‘LianJiaDB’下的集合“LianJiaRenting”中已经保存有我们爬取的数据,格式如下:{ “_id” : ObjectId(“5c6541b065b2fd1cf002c565”), “价格” : “7500元/月 (季付价)”, “房屋基本信息” : { “发布” : “20天前”, “入住” : “随时入住”, “租期” : “2~3年”, “看房” : “暂无数据”, “楼层” : “中楼层/6层”, “电梯” : “无”, “车位” : “暂无数据”, “用水” : “民水”, “用电” : “民电”, “燃气” : “有”, “采暖” : “集中供暖” }, “配套设施” : [ “电视”, “冰箱”, “洗衣机”, “空调”, “热水器”, “床”, “暖气”, “宽带”, “衣柜”, “天然气” ], “房源描述” : “【交通出行】 小区门口为八里庄南里公交车站,75,675等多路公交经过。地铁6号线十里堡站D口,距离地铁口400米,交通十分方便,便于出行。<br />\n【周边配套】 此房位置棒棒哒,有建设银行,中国银行,交通银行,邮政储蓄,果多美水果超市,购物,金旭菜市场,娱乐,休闲,便利。旁边首航超市,姥姥家春饼,味多美蛋糕店,生活方便。<br />\n【小区介绍】 该小区中此楼是1981建成,安全舒适,小区内主力楼盘为6层板楼,前后无遮挡,此楼是多见的板楼,楼层高视野好。<br />\n”, “联系经纪人” : { “宋玉恒” : “4000124028转7907” }, “地址与交通” : “距离6号线-十里堡192m”}查看当前爬取进度新开一个DOS端口,输入:> telnet 127.0.0.1 2232进行Telnet连接,可以使用命令操作查看当前爬虫的爬取状态。例如使用echo命令:$amipy> echo lianjia可以查看当前爬虫的状态:—————-Spider-lianjia——————– Name:lianjia Status:RUNNING- Class:LianjiaSpider- Success:25 Fail:0 Exception:0- Priority:0- SeedUrls:[‘https://bj.lianjia.com/zufang/’]- Path:D:\LianJia\LJproject\spiders\Lianjia- Session:<aiohttp.client.ClientSession object at 0x000000000386FE10>- StartAt:Thu Feb 14 20:30:21 2019- PausedAt:None- ResumeAt:None- StopAt:None- RestartAt:None- CloseAt:None————————————————– ...

February 14, 2019 · 3 min · jiezi

python turtle 书写新年快乐

文章链接:https://mp.weixin.qq.com/s/xYSKH_KLYfooIoelJH02Cg农历2018年的最后一篇文章,踏上回家的征途前,推荐一个Python的三方库turtle,是一个可以绘制图像文字的库。 这里的例子比较简单,就是依据各个点坐标连线最后形成文字的,先附上成品图的: 主要用到的几个方法: t.screensize(400, 400, “#fff”) 初始化画布,参数是宽、高、背景色; t.pensize(penSize) 设置画笔宽度; t.pencolor("#ff0000") 设置画笔的颜色; t.speed(10) 画笔的速度,参数范围 [1-10],越大速度越快,0-是最快; t.hideturtle() 可以隐藏绘制过程中的箭头; t.up() 抬起画笔,不绘制; t.goto(x,y) 定位到坐标(x,y); t.down() 落笔,开始绘制; t.done() 事件循环,不停绘制,图像一直存在import turtle as tt.screensize(400, 400, “#fff”)t.pensize(5)t.pencolor("#ff0000")t.speed(5)t.hideturtle()t.up()t.goto(-200,100)t.down()t.goto(-188,88)# …t.done()麻烦的是对各个点坐标的计算,要考虑到每一横竖的长短,整体的布局。附上github的链接:https://github.com/taixiang/turtle_year 最后祝大家新年快乐! 欢迎关注我的个人博客:https://www.manjiexiang.cn/ 更多精彩欢迎关注微信号:春风十里不如认识你 一起学习,一起进步,欢迎上车,有问题随时联系,一起解决!!!

January 31, 2019 · 1 min · jiezi

Centos7 安装 Odoo11

Centos7 安装 Odoo111 安装python3.6Centos7 基于稳定性考虑安装的是python2.7,而且默认的官方 yum 源中不提供 Python 3 的安装包,所以我们要先换一个提供python3的yum源– IUS 。 1、IUS软件源依赖与epel软件源包,首先要安装epel软件源包sudo yum install epel-release2、安装IUS软件源sudo yum install https://centos7.iuscommunity.org/ius-release.rpm3、安装python3.6sudo yum install python36usudo yum -y install python36u-develsudo yum -y install python36u-pip2 安装配置PostgreSQL数据库2.1 安装1、安装sudo yum install -y postgresql-server2、初始化service postgresql initdb3、启动服务systemctl start postgresql4、设置开机运行服务systemctl enable postgresql2.2 配置1、创建数据库和角色# 切换到 postgres 用户sudo su - postgres# 登录PostgreSQL控制台psql# 系统提示符会变为"postgres=#",表示这时已经进入了数据库控制台# 创建数据库用户dbuserCREATE USER dbuser WITH PASSWORD ‘password’ ENCODING=‘UTF8’;# 创建用户数据库CREATE DATABASE exampledb OWNER dbuser;# 将exampledb数据库的所有权限都赋予dbuserGRANT ALL PRIVILEGES ON DATABASE exampledb to dbuser;# 使用\q命令退出控制台(也可以直接按ctrl+D)\q如果在创建数据库时报如下错误:ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)则通过如下方式解决update pg_database set datallowconn = TRUE where datname = ’template0’; \c template0update pg_database set datistemplate = FALSE where datname = ’template1’; drop database template1;create database template1 with encoding = ‘UTF8’ LC_CTYPE = ’en_US.UTF-8’ LC_COLLATE = ’en_US.UTF-8’ template = template0;update pg_database set datallowconn = TRUE where datname = ’template1’;\c template1update pg_database set datallowconn = FALSE where datname = ’template0’;——————— 作者:东方-phantom 来源:CSDN 原文:https://blog.csdn.net/hkyw000/article/details/52817422 版权声明:本文为博主原创文章,转载请附上博文链接!2、配置这一步要修改两个配置文件:pg_hba.conf 和 postgresql.conf 。可以通过以下命令找到文件位置:sudo find / -name ‘filename’首先修改 pg_hba.conf :添加下面这行(这行是用于可远程连接的,如果想限制数据库只能本地访问的话,跳过)host all all 0.0.0.0/0 md5找到并修改下面这两行local all all peer md5host all all 127.0.0.1/32 ident md5修改 postgresql.conf (用于可远程连接,如不需要可调过):添加下面这行listen_addresses = ‘*‘修改完成之后,重启服务:systemctl restart postgresql至此,PostgreSQL 安装配置完成!3 安装 node.js 和 less插件Odoo 前端依赖 node.js 和 less,用以下命令安装:sudo yum install -y nodejssudo npm install -g less less-plugin-clean-css4 安装依赖yum install wkhtmltopdfyum install python-devel openldap-develyum install libxslt-devel libxml++-devel libxml2-develyum install gcc5 安装Odoo11这里我们用 pipenv 安装,首先安装 pipenvpip3.6 install pipenv拉取odoo11 代码后,在项目根目录创建虚拟环境并安装依赖pipenv –python python3.6 install -r requirments.txt安装时会有一个 win32 的模块安装失败,不用管,这个是windows系统开发时需要依赖的包。安装完成之后,创建一个 odoo 配置文件: odoo.conf 。 内容如下:[options];模块路径addons_path = odoo/addons,odoo/myaddons;超级管理员密码admin_passwd = admindb_host = localhostdb_port = 5432db_maxconn = 64;数据库名称db_name = ***;数据库用户db_user = ***;数据库密码db_password = ***然后运行如下命令启动 odoopython odoo-bin -c odoo.conf访问 127.0.0.1:8069 ,如果进入到odoo登录页面就说明安装成功了! ...

January 31, 2019 · 2 min · jiezi

Selenium实现付费音乐批量下载

必备环境废话每年回家都要帮我爸下些音乐,这对我来说都是轻车熟路!可当我打开网易云点击下载按钮的时候,可惜已物是人非啦!开个 VIP 其实也不贵,临时用用也就¥15!但 IT 男的尊严必须要有,于是开始徜徉于搜索引擎中最后在知乎中,搜索到一个网址 VIP付费音乐解析P.S.再次感谢提供该服务的作者!如果你下载的音乐数量不多,直接这里搜索下载,下载后修改文件名即可!并且在这个网址中点击播放列表-点击同步,可以同步网易云的歌单!之后批量下载即是下载这些网易云的歌单!但是下载某个歌单中的几百首歌,手动下载就不现实了!在点击同步中需要输入你的网易云 UID,这 UID 的获取方式如下:第一步打开网易云随便选中一首歌,右键复制链接然后随便找个地方粘贴这个链接,例如https://music.163.com/song?id=25727803&userid=275613591最后这串数字就是 UID!程序运行环境第一步安装一个python3,这个简单吧!贴上我的版本 python3.65,安装时注意勾选Add in path第二步下载FFmpeg,这是用来解析视频和音频的,作为you-get的辅助工具,下载点这里,下载后解压添加环境变量即可第三步安装you-get,这是个下载视频音频的神器,有兴趣可以深入研究!之后我打算写个下载任意视频的工具,嘿嘿这是后话了!安装方式很简单pip install you-get环境配置就这样,还是非常轻松的,下面会解释下代码源码完整代码from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsimport time, os# import thredingdef get_music_name_link(): main_handle = browser.current_window_handle fp = open(‘E:\Project_PY\file\musiclink.txt’,‘wb’) fp2 = open(‘E:\Project_PY\file\musicname.txt’,‘wb’) try: for i in list(range(2,400)): browser.switch_to_window(main_handle) txt = browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[2]/div[1]/div/div[%d]’ % i).text + ‘\n’ fp2.write(bytes(txt,encoding=‘utf-8’)) location = browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[2]/div[1]/div/div[%d]’ % i) ActionChains(browser).move_to_element(location).perform() browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[2]/div[1]/div/div[%d]/span[5]/div/span[2]’ % i).click() time.sleep(2) all_handles = browser.window_handles browser.switch_to_window(all_handles[-1]) # lastest url_link = browser.current_url + ‘\n’ fp.write(bytes(url_link,encoding=‘utf-8’)) browser.close() except Exception as e: print(‘get_music_name_link meet some problem! {}’.format(e)) fp.close() fp2.close()def download_music(list_name): with open(‘E:\Project_PY\file\musicname.txt’,‘r’,encoding=‘utf-8’) as fp1: music_name = fp1.readlines() len1 = len(music_name) fp2 = open(‘E:\Project_PY\file\musicname_format.txt’,‘w’,encoding=‘utf-8’) for i in range(3,len1,4): music_name_format = music_name[i].strip() + ‘\n’ fp2.write(music_name_format) fp2.close() with open(‘E:\Project_PY\file\musiclink.txt’,‘r’,encoding=‘utf-8’) as fp1: with open(‘E:\Project_PY\file\musicname_format.txt’,‘r’,encoding=‘utf-8’) as fp2: for music_link,music_name in zip(fp1.readlines(),fp2.readlines()): you_get_link = ‘you-get “{}” -o “E:\Project_PY\file\music\{}” -O “{}”’.format(music_link.strip(),list_name,music_name.strip()) you_get_link = you_get_link.strip() # print(you_get_link) os.system(you_get_link)url = ‘http://music.zhuolin.wang/'uid = input(‘please input your uid:’)options = webdriver.FirefoxOptions()options.add_argument(’–headless’)browser = webdriver.Firefox(firefox_options=options)browser.implicitly_wait(8)browser.get(url)# browser.maximize_window()browser.set_window_size(1000,100000)browser.find_element_by_xpath(’/html/body/div[3]/div/div[1]/div/span[3]’).click()# scroll = browser.find_element_by_xpath(’//*[@id=“mCSB_1_dragger_vertical”]’)# ActionChains(browser).drag_and_drop_by_offset(scroll,0,100).perform()# time.sleep(2)all_handles = browser.window_handlesbrowser.switch_to_window(all_handles[-1]) # lastesttime.sleep(1)browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[1]/div[1]/div/span/div[2]/span’).click()all_handles = browser.window_handlesbrowser.switch_to_window(all_handles[-1]) # lastesttime.sleep(1)browser.find_element_by_xpath(’/html/body/div[6]/div[2]/input’).send_keys(uid)browser.find_element_by_xpath(’/html/body/div[6]/div[3]/a[1]’).click()# t1 = threading.Thread(target=get_music_name)# t2 = threading.Thread(target=get_music_link)# t3 = threading.Thread(target=download_music)for i in list(range(3,100)): try: print(‘downloading song_list{}! please waiting….’.format(i)) browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[1]/div[1]/div/div[%d]/img’ % i).click() dir_name = browser.find_element_by_xpath(’/html/body/div[3]/div/div[2]/div[1]/div[1]/div/div[%d]/p’ % i).text time.sleep(1) get_music_name_link() download_music(dir_name) browser.find_element_by_xpath(’/html/body/div[3]/div/div[1]/div/span[3]’).click() time.sleep(1) all_handles = browser.window_handles browser.switch_to_window(all_handles[-1]) # lastest time.sleep(5) except Exception as e: print(‘get_song_list meet some problem! {}’.format(e))browser.quit()核心代码解释总共有三个函数:函数一get_music_name_link,主要是获取音乐名称以及音乐的下载链接函数二download_music,获取歌单名称,然后拼接下载链接和音乐名,调用you-get开始下载到对应目录函数三main,主要是利用 UID 获取歌单,以及批量下载歌单中的曲目需要注意的几个点:1.使用了sleep(1)休眠一秒,如果网络较慢需要将所有的sleep休眠时间加长2.所有的路径需要自己根据本机修改3.如果要修改代码一定要注意switch_to_window来切换窗口4.73行的for i in list(range(3,100))是用来选择下载的歌单,歌单从 1 开始计数程序演示输入网易云的 UID!然后静静的等待即可…此过程中会有部分音乐的播放声音,不喜欢可以开静音下当所有的链接解析完成后就会调用you-get下载,此过程会自动创建与歌单名相同的文件夹下载完成后P.S.如果要下载所有歌单,就不需要修改代码,直接输入网易云的 UID 运行即可!如果要下载某个具体的歌单只需要改动73行的这个循环for i in list(range(3,100)),所以说程序还是比较简单的,缺点可能就是没时间写 UI,而且也不太会 pyqt 之类的,只会点 MFC!所以将就用吧,功能还是很齐全的!END ...

January 23, 2019 · 2 min · jiezi

python中将list转为dict

最近在项目中经常遇到将list转为dict形式,之前都只会用for循环,取出list中的每个值,update到dict中。示例1scrabble_scores = [(1, “E A O I N R T L S U”), (2, “D G”), (3, “B C M P”), (4, “F H V W Y”), (5, “K”), (8, “J X”), (10, “Q Z”)]如何将上面的list拆分成key为字母,value为分数呢?LETTER_SCORES = {letter: score for score, letters in scrabble_scores for letter in letters.split()}通过上式处理后,就会形成{“A”: 1……….}此类形式。首先通过split()函数将字母分开,然后取出letters中的letter作为字典的key值,将分值作为value。示例2Letter = namedtuple(‘Letter’, ’name amount value’)distribution = [Letter(name=‘A’, amount=‘9’, value=‘1’), Letter(name=‘B’, amount=‘2’, value=‘3’), Letter(name=‘C’, amount=‘2’, value=‘3’), Letter(name=‘D’, amount=‘4’, value=‘2’), Letter(name=‘E’, amount=‘12’, value=‘1’), Letter(name=‘F’, amount=‘2’, value=‘4’), Letter(name=‘G’, amount=‘3’, value=‘2’), Letter(name=‘H’, amount=‘2’, value=‘4’), Letter(name=‘I’, amount=‘9’, value=‘1’), Letter(name=‘J’, amount=‘1’, value=‘8’), Letter(name=‘K’, amount=‘1’, value=‘5’), Letter(name=‘L’, amount=‘4’, value=‘1’), Letter(name=‘M’, amount=‘2’, value=‘3’), Letter(name=‘N’, amount=‘6’, value=‘1’), Letter(name=‘O’, amount=‘8’, value=‘1’), Letter(name=‘P’, amount=‘2’, value=‘3’), Letter(name=‘Q’, amount=‘1’, value=‘10’), Letter(name=‘R’, amount=‘6’, value=‘1’), Letter(name=‘S’, amount=‘4’, value=‘1’), Letter(name=‘T’, amount=‘6’, value=‘1’), Letter(name=‘U’, amount=‘4’, value=‘1’), Letter(name=‘V’, amount=‘2’, value=‘4’), Letter(name=‘W’, amount=‘2’, value=‘4’), Letter(name=‘X’, amount=‘1’, value=‘8’), Letter(name=‘Y’, amount=‘2’, value=‘4’), Letter(name=‘Z’, amount=‘1’, value=‘10’)]如何将上面的distribution中的name和value转换成dict形式?首先可以先将name和value值分别放到两个list中,可以通过下面代码实现:names = [letter.name for letter in distribution]values = [int(letter.value) for letter in distribution]然后可以通过zip()函数将name和value一一对应起来:zip(names, values)for i in zip(names, values): print(i)通过循环打印可以发现,name和value已经一一对应上了。最后将得到的由元组组成的list直接转为dict,在这边只需要直接用dict()函数即可。所以,实现上述功能需求,只需要下面一行代码:LETTER_SCORES = dict(zip( [letter.name for letter in distribution], [int(letter.value) for letter in distribution] ))得到的结果为:{‘A’: 1, ‘B’: 3, ‘C’: 3, ‘D’: 2, ‘E’: 1, ‘F’: 4, ‘G’: 2, ‘H’: 4, ‘I’: 1, ‘J’: 8, ‘K’: 5, ‘L’: 1, ‘M’: 3, ‘N’: 1, ‘O’: 1, ‘P’: 3, ‘Q’: 10, ‘R’: 1, ‘S’: 1, ‘T’: 1, ‘U’: 1, ‘V’: 4, ‘W’: 4, ‘X’: 8, ‘Y’: 4, ‘Z’: 10} ...

January 21, 2019 · 2 min · jiezi

Python的virtualenv使用

virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题。安装virtualenvpip3 install virtualenv使用virtualenv$ virtualenv [OPTIONS] DEST_DIR选项:–version 显示当前版本号。-h, –help 显示帮助信息。-v, –verbose 显示详细信息。-q, –quiet 不显示详细信息。-p PYTHON_EXE 指定所用的python解析器的版本比如 –python=python2.5 就使用2.5版本的解析器创建新的隔离环境。 默认使用的是当前系统安装(/usr/bin/python)的python解析器–clear 清空非root用户的安装,并重头开始创建隔离环境。–no-site-packages 默认,令隔离环境不能访问系统全局的site-packages目录。–system-site-packages 令隔离环境可以访问系统全局的site-packages目录。可以使用virtualenv –no-site-packages venv创建一个干净的虚拟环境,与原来的全局packages的隔绝。进入虚拟环境在Posix系统(*nix/BSD)中,用法如下:source venv/bin/activate在win中,直接执行Scripts目录下的activate:.\venv\Scripts\activate进入后在命令行前面会出现(venv)退出虚拟环境在Posix系统(*nix/BSD)中:deactivatewin:deactivate.bat常用命令记录安装的第三方模块pip freeze > requirements.txt安装txt文件里所记录的所有第三方模块pip install -r requirements.txt在编译器中配置虚拟环境pyCharm在file-setting-project-Project interpreter 中进行配置VScode在usersetting中的用户设置中设置:

January 20, 2019 · 1 min · jiezi

Python 利用 PIL 给图片增加特效

from PIL import Image, ImageFilter# 打开一个jpg图像文件,注意是当前路径:im = Image.open(‘Penguins.jpg’)# 模糊im2 = im.filter(ImageFilter.BLUR)# 模糊可设置模糊的程度im22 = im.filter(ImageFilter.BoxBlur(200))# 轮廓滤波im3 = im.filter(ImageFilter.CONTOUR)# 边缘增强滤波(锐化)im4 = im.filter(ImageFilter.EDGE_ENHANCE)# 浮雕滤波im5 = im.filter(ImageFilter.EMBOSS)# 寻找边缘信息的滤波im6 = im.filter(ImageFilter.FIND_EDGES)im2.save(‘BLUR.jpg’, ‘jpeg’)im3.save(‘CONTOUR.jpg’, ‘jpeg’)im4.save(‘EDGE_ENHANCE.jpg’, ‘jpeg’)im5.save(‘EMBOSS.jpg’, ‘jpeg’)im6.save(‘FIND_EDGES.jpg’, ‘jpeg’)im22.save(‘BoxBlur(200).jpg’, ‘jpeg’)图片如下

January 18, 2019 · 1 min · jiezi

python中字符串的rstrip()方法

今天在刷Bite 105. Slice and dice时遇到的一个问题,判断一个字符串是否以’.‘或者’!‘结尾,如果以这两个字符结尾,则去除这两个字符。自己写的函数:results = [] text_list = text.split(’\n’) print(text_list) for line in text_list: if line: new_line = line.strip() if new_line[0] in ascii_lowercase: line_list = new_line.split(’ ‘) if line_list[-1][-1] != ‘.’ and line_list[-1][-1] != ‘!’: results.append(line_list[-1]) else: results.append(line_list[-1][0:-1]) return results可以看到,在判断和去除这两个字符的时候,用了比较笨的方法,就是直接取字符串的[0:-1],后来查资料发现,python字符串中提供了rstrip()方法可以直接实现该功能,修改后的代码如下: results = [] for line in text.strip().split(’\n’): line = line.strip() if line[0] not in ascii_lowercase: continue words = line.split() last_word_stripped = words[-1].rstrip(’!.’) results.append(last_word_stripped) return results查看了该方法的实现: def rstrip(self, *args, **kwargs): # real signature unknown """ Return a copy of the string with trailing whitespace removed. If chars is given and not None, remove characters in chars instead. """ pass发现如果没有给该方法传参数,该方法会默认去掉字符串结尾的空格,如果传参了,就会去掉字符串中以传参结尾的。其实该练习中,还有ascii_lowercase值得注意,可以用来判断是否为小写字母!!! ...

January 16, 2019 · 1 min · jiezi

python 生成18年写过的博客词云

文章链接:https://mp.weixin.qq.com/s/NmJjTEADV6zKdT–2DXq9Q回看18年,最有成就的就是有了自己的 博客网站,坚持记录,写文章,累计写了36篇了,从一开始的难以下手,到现在成为一种习惯,虽然每次写都会一字一句斟酌,但是每次看到产出,内心还是开心的,享受这样的过程。 这篇文章就是用python 生成自己写的博客词云,平常写的博客都是markdown 格式的,直接把文件传到后台,前端用js去解析文件显示的,所以我这里处理数据就不需要去爬虫网站,直接读文件处理的。 关于生成词云图的,在另外两篇文章中也有介绍过: [python itchat 爬取微信好友信息,生成词云](https://mp.weixin.qq.com/s/4E… python爬虫学习:爬虫QQ说说并生成词云图 markdown文件处理,遍历文件夹,匹配md 后缀的文件,读文件,这里的root 是文件夹的绝对路径。import ostotal = ““file_list = os.listdir(root)for file in file_list: //处理md文件 if os.path.splitext(file)[1] == “.md”: path = os.path.join(root,file) text = open(path, encoding=‘utf-8’).read() //最终得到的字符串 total = total + “\n” + text得到所有的文本之后,使用结巴分词 pip3 install jieba,处理成单个的词语。import jiebawordlist = jieba.cut(total, cut_all=True)wl = " “.join(wordlist)因为平常写的文章里有很多的代码,这里可以正则只留下中文,然后再处理中文字符。import rerec = re.compile(”[^\u4E00-\u9FA5]")total = rec.sub(””, total)wordlist = jieba.cut(total, cut_all=True)wl = " “.join(wordlist)最后就是生成词云,采用WordCloud的库wc = WordCloud( # 设置背景颜色 background_color=“white”, # 设置最大显示的词云数 max_words=1000, # 这种字体都在电脑字体中,window在C:\Windows\Fonts\下,mac下的是/System/Library/Fonts/PingFang.ttc 字体 font_path=‘C:\Windows\Fonts\STFANGSO.ttf’, height=2000, width=2000, # 设置字体最大值 max_font_size=250, # 设置有多少种随机生成状态,即有多少种配色方案 random_state=30,)myword = wc.generate(wl) # 生成词云# 展示词云图plt.imshow(myword)plt.axis(“off”)wc.to_file(‘blog.png’) # 保存图片plt.ion()plt.pause(5)plt.close() # 图片显示5s,之后关闭最终的结果显示图,除去代码之后,看这些词,不少还是跟android相关的,也是平常经常会提到的词汇。 欢迎关注我的个人博客:https://www.manjiexiang.cn/ 更多精彩欢迎关注微信号:春风十里不如认识你 一起学习,一起进步,欢迎上车,有问题随时联系,一起解决!!! ...

January 13, 2019 · 1 min · jiezi

tensorflow安装教程

安装Windows下安装python环境安装pip安装virtualenv (pip3 install -U pip virtualenv)pip 安装TensorFlow步骤:创建虚拟环境 virtualenv –system-site-packages -p python3 ./venv进入虚拟环境 venv\Scripts\activate更新pip pip install –upgrade pip展示 venv 中已安装的软件包 pip list使用完 TensorFlow 后,方可推出 venv 虚拟环境 deactivate安装TensorFlow pip install –upgrade tensorflow这里需要注意python3.6在Windows下必须使用64 bit的版本,否则安装不成功验证安装 python -c “import tensorflow as tf;tf.enable_eager_execution();print(tf.reduce_sum(tf.random_normal([1000, 1000])))“安装 Jupyter NoteBook (venv) $ pip install jupyter (venv) $ python -m ipykernel install –user –name=venvdocker下安装安装镜像 docker pull tensorflow/tensorflow:nightly-jupyter启动镜像docker run -it -p 8888:8888 -v $(notebook-examples-path):/tf/notebookstensorflow/tensorflow:nightly-jupyter感谢阅读,希望阁下在AI领域越走越远~

January 11, 2019 · 1 min · jiezi

python各类经纬度转换

import mathimport urllibimport jsonx_pi = 3.14159265358979324 * 3000.0 / 180.0pi = 3.1415926535897932384626 # a = 6378245.0 # 长半轴ee = 0.00669342162296594323 # 扁率class Geocoding: def init(self, api_key): self.api_key = api_key def geocode(self, address): """ 利用高德geocoding服务解析地址获取位置坐标 :param address:需要解析的地址 :return: """ geocoding = {’s’: ‘rsv3’, ‘key’: self.api_key, ‘city’: ‘全国’, ‘address’: address} geocoding = urllib.urlencode(geocoding) ret = urllib.urlopen("%s?%s" % (“http://restapi.amap.com/v3/geocode/geo", geocoding)) if ret.getcode() == 200: res = ret.read() json_obj = json.loads(res) if json_obj[‘status’] == ‘1’ and int(json_obj[‘count’]) >= 1: geocodes = json_obj[‘geocodes’][0] lng = float(geocodes.get(’location’).split(’,’)[0]) lat = float(geocodes.get(’location’).split(’,’)[1]) return [lng, lat] else: return None else: return Nonedef gcj02_to_bd09(lng, lat): "”" 火星坐标系(GCJ-02)转百度坐标系(BD-09) 谷歌、高德——>百度 :param lng:火星坐标经度 :param lat:火星坐标纬度 :return: """ z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * x_pi) theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * x_pi) bd_lng = z * math.cos(theta) + 0.0065 bd_lat = z * math.sin(theta) + 0.006 return [bd_lng, bd_lat]def bd09_to_gcj02(bd_lon, bd_lat): """ 百度坐标系(BD-09)转火星坐标系(GCJ-02) 百度——>谷歌、高德 :param bd_lat:百度坐标纬度 :param bd_lon:百度坐标经度 :return:转换后的坐标列表形式 """ x = bd_lon - 0.0065 y = bd_lat - 0.006 z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi) theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi) gg_lng = z * math.cos(theta) gg_lat = z * math.sin(theta) return [gg_lng, gg_lat]def wgs84_to_gcj02(lng, lat): """ WGS84转GCJ02(火星坐标系) :param lng:WGS84坐标系的经度 :param lat:WGS84坐标系的纬度 :return: """ if out_of_china(lng, lat): # 判断是否在国内 return lng, lat dlat = _transformlat(lng - 105.0, lat - 35.0) dlng = _transformlng(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * pi magic = math.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = math.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi) dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlng return [mglng, mglat]def gcj02_to_wgs84(lng, lat): """ GCJ02(火星坐标系)转GPS84 :param lng:火星坐标系的经度 :param lat:火星坐标系纬度 :return: """ if out_of_china(lng, lat): return lng, lat dlat = _transformlat(lng - 105.0, lat - 35.0) dlng = _transformlng(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * pi magic = math.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = math.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi) dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlng return [lng * 2 - mglng, lat * 2 - mglat]def bd09_to_wgs84(bd_lon, bd_lat): lon, lat = bd09_to_gcj02(bd_lon, bd_lat) return gcj02_to_wgs84(lon, lat)def wgs84_to_bd09(lon, lat): lon, lat = wgs84_to_gcj02(lon, lat) return gcj02_to_bd09(lon, lat)def _transformlat(lng, lat): ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \ 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng)) ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 * math.sin(2.0 * lng * pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(lat * pi) + 40.0 * math.sin(lat / 3.0 * pi)) * 2.0 / 3.0 ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 * math.sin(lat * pi / 30.0)) * 2.0 / 3.0 return retdef _transformlng(lng, lat): ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \ 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng)) ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 * math.sin(2.0 * lng * pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(lng * pi) + 40.0 * math.sin(lng / 3.0 * pi)) * 2.0 / 3.0 ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 * math.sin(lng / 30.0 * pi)) * 2.0 / 3.0 return retdef out_of_china(lng, lat): """ 判断是否在国内,不在国内不做偏移 :param lng: :param lat: :return: """ return not (73.66 < lng < 135.05 and lat > 3.86 and lat < 53.55)def baidu_to_google(lng, lat): result5 = bd09_to_wgs84(float(lng), float(lat)) return result5def google_to_baidu(lng, lat): result5 = wgs84_to_bd09(float(lng), float(lat)) return result5 ...

January 2, 2019 · 4 min · jiezi

Python 在图片加上消息通知的文字

一.需求:在头像加上消息通知图标二.实现1.导入PIL 包并导入相关的模块呢from PIL import Image, ImageFont, ImageDraw遇到问题:因为使用的是python3 直接导入PIL的安装PIL模块的时候报错,使用pip install PIL 安装PIL报错:Collecting PILCould not find a version that satisfies the requirement PIL (from versions: )No matching distribution found for PIL原因:PIL只支持python2.x ,所有使用python3 时候报错 解决方法:PIL 已经有一个分支项目,安装分支项目pillow同样支持PIL模块pip install Pillow2.PIL使用1>导入需要修改的图片image = Image.open('./images/icon.png')2>设置字体的字体和大小# font = ImageFont.truetype(字体, 字体大小) font = ImageFont.truetype('arial.ttf', 20) 3.调用ImageDraw.Draw() 方法处理图片```# 调用Draw方法,传入导入图片对象draw = ImageDraw.Draw(image)draw.text((65, 0), ‘5’, fill=(255, 10, 10), font=font)# draw.text方法是用来在图片上加上文字# draw.text((x, y), ‘5’, fill=(255, 10, 10), font=font)# (x,y)是一个元组用来表示生成的位置,x表x轴的位置,y表示在y轴的位置# 需要注意的是:坐标轴的原点是图片的左上角# ‘5’ 表示的是需要在图片上写入的文字# fill=(255, 10, 10) 表示的是RGB的色值# font=font 表示字体,传入定义好的字体```` 4.保存图片# ‘./images/change.png’’./images/‘保存的图片路径,../change.png需要保存的图片名# ‘png’ 图片保存的格式image.save(’./images/change.png’, ‘png’) ...

January 1, 2019 · 1 min · jiezi

python xlrd 读取excel

文章链接:https://mp.weixin.qq.com/s/fojkVO-AB2cCu7FtDtPBjw之前的文章介绍过关于写入excel表格的方法,近期自己在做一个网站,涉及到读取excel,然后把数据存到数据库,故把操作excel的过程记录下的。 pip3 install xlrd直接pip3安装。 为了演示方便,这里的excel文件直接和python文件放在一个目录下的,如果是项目中,需要注意excel的文件路径。# 操作excelexcel = xlrd.open_workbook(“test.xls”)excel.sheet_names() # 获取excel里的工作表sheet名称数组sheet = excel.sheet_by_index(0) #根据下标获取对应的sheet表sheet.row_values(0) #获取第一行的数据sheet.col_values(0) #获取第一列的数据sheet.nrows #获取总共的行数sheet.ncols #获取总共的列数假设我们需要第二行至最后一行的数据,就可以直接遍历获取了for i in range(1, sheet.nrows): row_list = sheet.row_values(i) # 每一行的数据在row_list 数组里对于单个的单元格可以通过sheet.cell(row,col) 参数就是row-行、col-列,这个方法得到的是cell对象,sheet.cell(0,0).value value是对应的单元格内容。 还有一种特殊的情况,合并单元格的: sheet.merged_cells 可以查看合并单元格的情况print(sheet.merged_cells)[(0, 1, 1, 3), (4, 10, 1, 2)](0, 1, 1, 3) 第一行 第2到3列合并 (4, 10, 1, 2) 第5到10行 第2列合并 前两个参数指行范围,后两个参数指列范围。 合并单元格的内容取值只有 合并的第一个单元格可以获取到值,其他为空。print(sheet.cell(0, 1).value)print(sheet.cell(4, 1).value)自己做的网站,数据就是从excel表格来的,所以就需要对excel表格进行操作,把数据写到数据库里面。我这边需要使用到的就是遍历excel行去取值,难度并不高,唯一要注意的就是excel的路径问题。media_root = os.path.join(settings.BASE_DIR, ‘upload/excel/’)word_path = media_root + “**.xls"这篇文章介绍的比较简单,但是用好了这些库,对我们日常使用还是很有帮助的,提升开发效率。 欢迎关注我的个人博客:https://www.manjiexiang.cn/ 更多精彩欢迎关注微信号:春风十里不如认识你 一起学习,一起进步,欢迎上车,有问题随时联系,一起解决!!!

December 23, 2018 · 1 min · jiezi

集合模块collections

collections是Python内建的一个集合模块,提供了许多有用的集合类。namedtuple我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:>>> p = (1, 2)但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。定义一个class又小题大做了,这时,namedtuple就派上了用场:>>> from collections import namedtuple>>> Point = namedtuple(‘Point’, [‘x’, ‘y’])>>> p = Point(1, 2)>>> p.x1>>> p.y2namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。这样一来,我们用namedtuple可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便。可以验证创建的Point对象是tuple的一种子类:>>> isinstance(p, Point)True>>> isinstance(p, tuple)True类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:namedtuple(‘名称’, [属性list]):Circle = namedtuple(‘Circle’, [‘x’, ‘y’, ‘r’])deque使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:>>> from collections import deque>>> q = deque([‘a’, ‘b’, ‘c’])>>> q.append(‘x’)>>> q.appendleft(‘y’)>>> qdeque([‘y’, ‘a’, ‘b’, ‘c’, ‘x’])deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。defaultdict(免因为没有key 报错KeyError)使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:>>> from collections import defaultdict>>> dd = defaultdict(lambda: ‘N/A’)>>> dd[‘key1’] = ‘abc’>>> dd[‘key1’] # key1存在’abc’>>> dd[‘key2’] # key2不存在,返回默认值’N/A’注意默认值是调用函数返回的,而函数在创建defaultdict对象时传入。除了在Key不存在时返回默认值,defaultdict的其他行为跟dict是完全一样的。OrderedDict使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。如果要保持Key的顺序,可以用OrderedDict:>>> from collections import OrderedDict>>> d = dict([(‘a’, 1), (‘b’, 2), (‘c’, 3)])>>> d # dict的Key是无序的{‘a’: 1, ‘c’: 3, ‘b’: 2}>>> od = OrderedDict([(‘a’, 1), (‘b’, 2), (‘c’, 3)])>>> od # OrderedDict的Key是有序的OrderedDict([(‘a’, 1), (‘b’, 2), (‘c’, 3)])注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:>>> od = OrderedDict()>>> od[‘z’] = 1>>> od[‘y’] = 2>>> od[‘x’] = 3>>> list(od.keys()) # 按照插入的Key的顺序返回[‘z’, ‘y’, ‘x’]OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key:from collections import OrderedDictclass LastUpdatedOrderedDict(OrderedDict):def init(self, capacity): super(LastUpdatedOrderedDict, self).init() self._capacity = capacitydef setitem(self, key, value): containsKey = 1 if key in self else 0 if len(self) - containsKey >= self._capacity: last = self.popitem(last=False) print(‘remove:’, last) if containsKey: del self[key] print(‘set:’, (key, value)) else: print(‘add:’, (key, value)) OrderedDict.setitem(self, key, value)ChainMapChainMap可以把一组dict串起来并组成一个逻辑上的dict。ChainMap本身也是一个dict,但是查找的时候,会按照顺序在内部的dict依次查找。什么时候使用ChainMap最合适?举个例子:应用程序往往都需要传入参数,参数可以通过命令行传入,可以通过环境变量传入,还可以有默认参数。我们可以用ChainMap实现参数的优先级查找,即先查命令行参数,如果没有传入,再查环境变量,如果没有,就使用默认参数。下面的代码演示了如何查找user和color这两个参数:from collections import ChainMapimport os, argparse# 构造缺省参数:defaults = { ‘color’: ‘red’, ‘user’: ‘guest’}# 构造命令行参数:parser = argparse.ArgumentParser()parser.add_argument(’-u’, ‘–user’)parser.add_argument(’-c’, ‘–color’)namespace = parser.parse_args()command_line_args = { k: v for k, v in vars(namespace).items() if v }# 组合成ChainMap:combined = ChainMap(command_line_args, os.environ, defaults)# 打印参数:print(‘color=%s’ % combined[‘color’])print(‘user=%s’ % combined[‘user’])没有任何参数时,打印出默认参数:$ python3 use_chainmap.py color=reduser=guest当传入命令行参数时,优先使用命令行参数:$ python3 use_chainmap.py -u bobcolor=reduser=bob同时传入命令行参数和环境变量,命令行参数的优先级较高:$ user=admin color=green python3 use_chainmap.py -u bobcolor=greenuser=bobCounterCounter是一个简单的计数器,例如,统计字符出现的个数:>>> from collections import Counter>>> c = Counter()>>> for ch in ‘programming’:… c[ch] = c[ch] + 1…>>> cCounter({‘g’: 2, ’m’: 2, ‘r’: 2, ‘a’: 1, ‘i’: 1, ‘o’: 1, ’n’: 1, ‘p’: 1})Counter实际上也是dict的一个子类,上面的结果可以看出,字符’g’、’m’、‘r’各出现了两次,其他字符各出现了一次。小结collections模块提供了一些有用的集合类,可以根据需要选用。参考源码use_collections.py ...

December 19, 2018 · 2 min · jiezi

python摘要算法(又称哈希算法、散列算法)

摘要算法简介Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。举个例子,你写了一篇文章,内容是一个字符串’how to use python hashlib - by Michael’,并附上这篇文章的摘要是'2d73d4f15c0db7f5ecb321b6a65e5d6d’。如果有人篡改了你的文章,并发表为’how to use python hashlib - by Bob’,你可以一下子指出Bob篡改了你的文章,因为根据’how to use python hashlib - by Bob’计算出的摘要不同于原始文章的摘要。可见,摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:import hashlibmd5 = hashlib.md5()md5.update(‘how to use md5 in python hashlib?’.encode(“utf8”))print(md5.hexdigest())计算结果如下:d26a53750bc40b38b65a520292f69306如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:md5 = hashlib.md5()md5.update(‘how to use md5 in ‘.encode(“utf8”))md5.update(‘python hashlib?’.encode(“utf8”))print(md5.hexdigest())试试改动一个字母,看看计算的结果是否完全不同。MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:import hashlibsha1 = hashlib.sha1()sha1.update(‘how to use sha1 in ‘.encode(“utf8”))sha1.update(‘python hashlib?’.encode(“utf8”))print(sha1.hexdigest())SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。有没有可能两个不同的数据通过某个摘要算法得到了相同的摘要?完全有可能,因为任何摘要算法都是把无限多的数据集合映射到一个有限的集合中。这种情况称为碰撞,比如Bob试图根据你的摘要反推出一篇文章’how to learn hashlib in python - by Bob’,并且这篇文章的摘要恰好和你的文章完全一致,这种情况也并非不可能出现,但是非常非常困难。摘要算法应用摘要算法能应用到什么地方?举个常用例子:任何允许用户登录的网站都会存储用户登录的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中:name | password——–+———-michael | 123456bob | abc999alice | alice2008如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:username | password———+———————————michael | e10adc3949ba59abbe56e057f20f883ebob | 878ef96e86145580c38c87f0410ad153alice | 99b1c2188db85afee403b1536010c2c9当用户登录时,首先计算用户输入的明文口令的MD5,然后和数据库存储的MD5对比,如果一致,说明口令输入正确,如果不一致,口令肯定错误。练习:根据用户输入的口令,计算出存储在数据库中的MD5口令:def calc_md5(password):pass存储MD5的好处是即使运维人员能访问数据库,也无法获知用户的明文口令。练习:设计一个验证用户登录的函数,根据用户输入的口令是否正确,返回True或False:db = { ‘michael’: ’e10adc3949ba59abbe56e057f20f883e’, ‘bob’: ‘878ef96e86145580c38c87f0410ad153’, ‘alice’: ‘99b1c2188db85afee403b1536010c2c9’}def login(user, password): pass采用MD5存储口令是否就一定安全呢?也不一定。假设你是一个黑客,已经拿到了存储MD5口令的数据库,如何通过MD5反推用户的明文口令呢?暴力破解费事费力,真正的黑客不会这么干。考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:’e10adc3949ba59abbe56e057f20f883e’: ‘123456’‘21218cca77804d2ba1922c33e0151105’: ‘888888’‘5f4dcc3b5aa765d61d8327deb882cf99’: ‘password’这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:def calc_md5(password): return get_md5(password + ’the-Salt’)经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。练习:根据用户输入的登录名和口令模拟用户注册,计算更安全的MD5:db = {}def register(username, password): db[username] = get_md5(password + username + ’the-Salt’)然后,根据修改后的MD5算法实现用户登录的验证:def login(username, password): pass 小结摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。 ...

December 19, 2018 · 1 min · jiezi

Python2.x与3.x版本区别

Python的3.0版本,常被称为Python 3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容。许多针对早期Python版本设计的程式都无法在Python 3.0上正常执行。为了照顾现有程式,Python 2.6作为一个过渡版本,基本使用了Python 2.x的语法和库,同时考虑了向Python 3.0的迁移,允许使用部分Python 3.0的语法与函数。新的Python程式建议使用Python 3.0版本的语法。除非执行环境无法安装Python 3.0或者程式本身使用了不支援Python 3.0的第三方库。目前不支援Python 3.0的第三方库有Twisted, py2exe, PIL等。大多数第三方库都正在努力地相容Python 3.0版本。即使无法立即使用Python 3.0,也建议编写相容Python 3.0版本的程式,然后使用Python 2.6, Python 2.7来执行。Python 3.0的变化主要在以下几个方面:print 函数print语句没有了,取而代之的是print()函数。 Python 2.6与Python 2.7部分地支持这种形式的print语法。在Python 2.6与Python 2.7里面,以下三种形式是等价的:print “fish"print (“fish”) #注意print后面有个空格print(“fish”) #print()不能带有任何其它参数然而,Python 2.6实际已经支持新的print()语法:from future import print_functionprint(“fish”, “panda”, sep=’, ‘)UnicodePython 2 有 ASCII str() 类型,unicode() 是单独的,不是 byte 类型。现在, 在 Python 3,我们最终有了 Unicode (utf-8) 字符串,以及一个字节类:byte 和 bytearrays。由于 Python3.X 源码文件默认使用utf-8编码,这就使得以下代码是合法的:>>> 中国 = ‘china’ >>>print(中国) chinaPython 2.x>>> str = “我爱北京天安门”>>> str’\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8’>>> str = u"我爱北京天安门”>>> stru’\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8’Python 3.x>>> str = “我爱北京天安门”>>> str’我爱北京天安门’除法运算Python中的除法较其它语言显得非常高端,有套很复杂的规则。Python中的除法有两个运算符,/和//首先来说/除法:在python 2.x中/除法就跟我们熟悉的大多数语言,比如Java啊C啊差不多,整数相除的结果是一个整数,把小数部分完全忽略掉,浮点数除法会保留小数点的部分得到一个浮点数的结果。在python 3.x中/除法不再这么做了,对于整数之间的相除,结果也会是浮点数。Python 2.x:>>> 1 / 2 0 >>> 1.0 / 2.0 0.5 Python 3.x: >>> 1/2 0.5而对于//除法,这种除法叫做floor除法,会对除法的结果自动进行一个floor操作,在python 2.x和python 3.x中是一致的。python 2.x:>>> -1 // 2-1python 3.x:>>> -1 // 2-1注意的是并不是舍弃小数部分,而是执行 floor 操作,如果要截取整数部分,那么需要使用 math 模块的 trunc 函数python 3.x:>>> import math>>> math.trunc(1 / 2)0>>> math.trunc(-1 / 2)0异常在 Python 3 中处理异常也轻微的改变了,在 Python 3 中我们现在使用 as 作为关键词。捕获异常的语法由 except exc, var 改为 except exc as var。使用语法except (exc1, exc2) as var可以同时捕获多种类别的异常。 Python 2.6已经支持这两种语法。在2.x时代,所有类型的对象都是可以被直接抛出的,在3.x时代,只有继承自BaseException的对象才可以被抛出。2.x raise语句使用逗号将抛出对象类型和参数分开,3.x取消了这种奇葩的写法,直接调用构造函数抛出对象即可。在2.x时代,异常在代码中除了表示程序错误,还经常做一些普通控制结构应该做的事情,在3.x中可以看出,设计者让异常变的更加专一,只有在错误发生的情况才能去用异常捕获语句来处理。xrange在 Python 2 中 xrange() 创建迭代对象的用法是非常流行的。比如: for 循环或者是列表/集合/字典推导式。这个表现十分像生成器(比如。“惰性求值”)。但是这个 xrange-iterable 是无穷的,意味着你可以无限遍历。由于它的惰性求值,如果你不得仅仅不遍历它一次,xrange() 函数 比 range() 更快(比如 for 循环)。尽管如此,对比迭代一次,不建议你重复迭代多次,因为生成器每次都从头开始。在 Python 3 中,range() 是像 xrange() 那样实现以至于一个专门的 xrange() 函数都不再存在(在 Python 3 中 xrange() 会抛出命名异常)。import timeitn = 10000def test_range(n): return for i in range(n): passdef test_xrange(n): for i in xrange(n): pass Python 2print ‘Python’, python_version()print ‘\ntiming range()’ %timeit test_range(n)print ‘\n\ntiming xrange()’ %timeit test_xrange(n)Python 2.7.6timing range()1000 loops, best of 3: 433 µs per looptiming xrange()1000 loops, best of 3: 350 µs per loopPython 3print(‘Python’, python_version())print(’\ntiming range()’)%timeit test_range(n)Python 3.4.1timing range()1000 loops, best of 3: 520 µs per loopprint(xrange(10))NameError Traceback (most recent call last)<ipython-input-5-5d8f9b79ea70> in <module>()—-> 1 print(xrange(10))NameError: name ‘xrange’ is not defined八进制字面量表示八进制数必须写成0o777,原来的形式0777不能用了;二进制必须写成0b111。新增了一个bin()函数用于将一个整数转换成二进制字串。 Python 2.6已经支持这两种语法。在Python 3.x中,表示八进制字面量的方式只有一种,就是0o1000。python 2.x>>> 0o1000512>>> 01000512python 3.x>>> 01000 File “<stdin>”, line 1 01000 ^SyntaxError: invalid token>>> 0o1000512不等运算符Python 2.x中不等于有两种写法 != 和 <>Python 3.x中去掉了<>, 只有!=一种写法,还好,我从来没有使用<>的习惯去掉了repr表达式Python 2.x 中反引号相当于repr函数的作用Python 3.x 中去掉了``这种写法,只允许使用repr函数,这样做的目的是为了使代码看上去更清晰么?不过我感觉用repr的机会很少,一般只在debug的时候才用,多数时候还是用str函数来用字符串描述对象。def sendMail(from_: str, to: str, title: str, body: str) -> bool: pass多个模块被改名(根据PEP8)旧的名字 新的名字_winreg winregConfigParser configparsercopy_reg copyregQueue queueSocketServer socketserverrepr reprlibStringIO模块现在被合并到新的io模组内。 new, md5, gopherlib等模块被删除。 Python 2.6已经支援新的io模组。httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib被合并到http包内。取消了exec语句,只剩下exec()函数。 Python 2.6已经支援exec()函数。5.数据类型1)Py3.X去除了long类型,现在只有一种整型——int,但它的行为就像2.X版本的long2)新增了bytes类型,对应于2.X版本的八位串,定义一个bytes字面量的方法如下:>>> b = b’china’ >>> type(b) <type ‘bytes’> str对象和bytes对象可以使用.encode() (str -> bytes) or .decode() (bytes -> str)方法相互转化。>>> s = b.decode() >>> s ‘china’ >>> b1 = s.encode() >>> b1 b’china'3)dict的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有 dict.has_key(),用 in替代它吧 。 ...

December 19, 2018 · 2 min · jiezi

Python3爬取英雄联盟英雄皮肤大图

前言上篇文章,说到了,爬取LOL英雄皮肤的高清图片,最近有事,也没怎么去研究,所以,现在才去看了下,并且写了Python脚本来抓取皮肤图片。需要说明一下,这个脚本有部分英雄没有抓取到,但是具体原因,我目前还没搞懂,我是相当纳闷的。大家有兴趣的,可以看看后面遗留问题,一起研究下。爬虫思路初步尝试我先查看了network,并没有发现有可用的API;然后又用bs4去分析英雄列表页,但是请求到html里面,并没有英雄列表,在英雄列表的节点上,只有“正在加载中”这样的字样;同样的方法,分析英雄详情也是这种情况,所以我猜测,这些数据应该是Javascript负责加载的。继续尝试然后我就查看了英雄列表的源代码,查看外部引入的js文件,以及行内的js脚本,大概在368行,发现了有处理英雄列表的js注释,然后继续往下读这些代码,发现了第一个彩蛋,也就是他引入了一个champion.js的文件,我猜测,这个应该就是英雄列表大全了,然后我打开了这个链接的js,一眼看过去,黑麻麻一片,然后格式化了一下压缩的js,确定这就是英雄列表的js数据文件了。接着尝试前面通过查看列表的源代码,找到了英雄列表的js数据文件,那么,我继续随机点开了一个英雄的详情,然后查看英雄详情源代码,然后大概在568行看到有一个showSkin的js方法,通过这里,发现了第二个彩蛋,也就是皮肤图片的URL地址拼接方法。最后尝试上面找到了皮肤图片URL的拼接方法,并且发现了一行很关键的代码var skin =LOLherojs.champion[heroid].data.skins,也就是,这个skin变量,就是英雄皮肤的所有图片数组,但是这个文件内,并没有LOLherojs这个变量,也就是外部引入的,所以,需要继续查看下面的源代码,找到引入这个变量的位置,果不其然,在757行,发现了最后一个彩蛋,也就是,英雄皮肤的js文件,通过这里可以知道,每个英雄都有一个单独的js文件,并且知道了这个js文件的URL拼接方法。思路总结通过上面的分析,我们就得到了爬取LOL皮肤图片的所有数据准备了,也就是,直接,只需要提取js中的英雄列表以及英雄详情数据,就可实现我们的需求了。下面是运行后抓取到的图片……运行环境Python运行环境:python3.6 用到的模块:requests、json、urllib、os 未安装的模块,请使用pip instatll进行安装,例如:pip install requests完整代码其他啥的废话就不多说了,直接上完整代码,有问题,直接留言给我就行,另外,代码已上传GitHub。再说明一下,那些有问题的英雄详情的js文件,大家有时间也可以琢磨下,或者有其他的更加快捷的爬取这些图片的方法,也可以拿出来交流和讨论,谢谢。#!/usr/bin/env python# -- coding: utf-8 --“““抓取英雄联盟英雄全皮肤author: gxcuizydate: 2018-11-13"““import requestsimport jsonfrom urllib import parseimport osclass GetLolSkin(object): “““抓取LOL英雄皮肤””” def init(self): “““初始化变量””” self.hero_url = ‘https://lol.qq.com/biz/hero/champion.js' self.hero_detail_url = ‘http://lol.qq.com/biz/hero/' self.skin_folder = ‘skin’ self.skin_url = ‘https://ossweb-img.qq.com/images/lol/web201310/skin/big' @staticmethod def get_html(url): “““下载html””” request = requests.get(url) request.encoding = ‘gbk’ if request.status_code == 200: return request.text else: return “{}” def get_hero_list(self): “““获取英雄的完整信息列表””” hero_js = self.get_html(self.hero_url) # 删除左右的多余信息,得到json数据 out_left = “if(!LOLherojs)var LOLherojs={};LOLherojs.champion=” out_right = ‘;’ hero_list = hero_js.replace(out_left, ‘’).rstrip(out_right) return json.loads(hero_list) def get_hero_info(self, hero_id): “““获取英雄的详细信息””” # 获取js详情 detail_url = parse.urljoin(self.hero_detail_url, hero_id + ‘.js’) detail_js = self.get_html(detail_url) # 删除左右的多余信息,得到json数据 out_left = “if(!herojs)var herojs={champion:{}};herojs[‘champion’][%s]=” % hero_id out_right = ‘;’ hero_info = detail_js.replace(out_left, ‘’).rstrip(out_right) return json.loads(hero_info) def download_skin_list(self, skin_list, hero_name): “““下载皮肤列表””” # 循环下载皮肤 for skin_info in skin_list: # 拼接图片名字 if skin_info[’name’] == ‘default’: skin_name = ‘默认皮肤’ else: if ’ ’ in skin_info[’name’]: name_info = skin_info[’name’].split(’ ‘) skin_name = name_info[0] else: skin_name = skin_info[’name’] hero_skin_name = hero_name + ‘-’ + skin_name + ‘.jpg’ self.download_skin(skin_info[‘id’], hero_skin_name) def download_skin(self, skin_id, skin_name): “““下载皮肤图片””” # 下载图片 img_url = self.skin_url + skin_id + ‘.jpg’ request = requests.get(img_url) if request.status_code == 200: print(‘downloading……%s’ % skin_name) img_path = os.path.join(self.skin_folder, skin_name) with open(img_path, ‘wb’) as img: img.write(request.content) else: print(‘img error!’) def make_folder(self): “““初始化,创建图片文件夹””” if not os.path.exists(self.skin_folder): os.mkdir(self.skin_folder) def run(self): # 获取英雄列表信息 hero_json = self.get_hero_list() hero_keys = hero_json[‘keys’] # 循环遍历英雄 for hero_id, hero_code in hero_keys.items(): hero_name = hero_json[‘data’][hero_code][’name’] hero_info = self.get_hero_info(hero_id) if hero_info: skin_list = hero_info[‘result’][hero_id][‘skins’] # 下载皮肤 self.download_skin_list(skin_list, hero_name) else: print(‘英雄【%s】的皮肤获取有问题……’ % hero_name)# 程序执行入口if name == ‘main’: lol = GetLolSkin() # 创建图片存储文件 lol.make_folder() # 执行脚本 lol.run() ...

November 14, 2018 · 2 min · jiezi

Python爬取王者荣耀英雄皮肤高清图片

前言临下班前,看到群里有人在讨论用王者农药的一些皮肤作为电脑的壁纸,什么高清的,什么像素稍低的,网上查了一手,也有,但像素都不一样,所以,我就想着,自己去官网直接爬他的高清皮肤就好了,然后就有了这边文章说的主题了。爬图思路找到英雄列表进入官网,然后进入英雄介绍,查看更多英雄,就能看到全部的英雄了,也就是下面的这个链接英雄列表:https://pvp.qq.com/web201605/herolist.shtml英雄详情点击每个英雄进来,就可以看到每个英雄的详细信息,基本介绍以及皮肤展示,而我们需要爬取的皮肤,就在右下角那里,鼠标放上去,就可以逐个展示该皮肤了小鲁班的详细信息:https://pvp.qq.com/web201605/herodetail/112.shtml分析皮肤图片URL从上面的这张鲁班的图片中我们可以看到,通过F12定位到皮肤的小图片位置,li元素里有一个img的元素,其中img的src和data-imgname这两个属性,查看一下,就不难知道,src的属性值是小图,而data-imgname则是我们需要的大图URL,但是查看源码,就会发现,在html中,并没有这个属性,所以,需要我们分析这个URL的规律来得到其他英雄的皮肤图片,分析也不难发现,112就是英雄的id,而bigskin-2里面的2即表示这个英雄的第几张皮肤图片开始编写爬虫脚本第一步:定义一些常用变量第二步:抓取所有英雄列表第三步:循环遍历,分析每个英雄皮肤节点第四步:下载图片第五步:爬虫结束完整源码感觉上面七七八八的,说了些啥呀,真是墨迹,还不如直接上代码实在,好吧,我错了,马上交出源码,请各位看官饶恕,同时,代码我也上传了交友网站GitHub。#!/usr/bin/env python# -- coding: utf-8 --“““抓取王者荣耀皮肤author: gxcuizydate: 2018-11-06"““import requestsfrom bs4 import BeautifulSoupfrom urllib import parseimport osclass Skin(object): def init(self): # 英雄的json数据 self.hero_url = ‘https://pvp.qq.com/web201605/js/herolist.json' # 英雄详细页的通用url前缀信息 self.base_url = ‘https://pvp.qq.com/web201605/herodetail/' # 英雄详细页url后缀信息 self.detail_url = ’’ # 图片存储文件夹 self.img_folder = ‘skin’ # 图片url的通用前缀 self.skin_url = ‘https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/' # 图片url的后缀信息 self.skin_detail_url = ’’ def get_hero(self): “““获取英雄的json数据””” request = requests.get(self.hero_url) hero_list = request.json() return hero_list def get_hero_skin(self, hero_name, hero_no): “““获取详细页英雄皮肤展示的信息,并爬图””” url = parse.urljoin(self.base_url, self.detail_url) request = requests.get(url) request.encoding = ‘gbk’ html = request.text # 获取皮肤信息的节点 soup = BeautifulSoup(html, ’lxml’) skip_list = soup.select(’.pic-pf-list3’) for skin_info in skip_list: # 获取皮肤名称 img_names = skin_info.attrs[‘data-imgname’] name_list = img_names.split(’|’) skin_no = 1 # 循环下载皮肤图片 for skin_name in name_list: self.skin_detail_url = ‘%s/%s-bigskin-%s.jpg’ % (hero_no, hero_no, skin_no) skin_no += 1 img_name = hero_name + ‘-’ + skin_name + ‘.jpg’ self.download_skin(img_name) def download_skin(self, img_name): “““下载皮肤图片””” img_url = parse.urljoin(self.skin_url, self.skin_detail_url) request = requests.get(img_url) if request.status_code == 200: print(‘download-%s’ % img_name) img_path = os.path.join(self.img_folder, img_name) with open(img_path, ‘wb’) as img: img.write(request.content) else: print(‘img error!’) def make_folder(self): “““创建图片存储文件夹””” if not os.path.exists(self.img_folder): os.mkdir(self.img_folder) def run(self): “““脚本执行入口””” self.make_folder() hero_list = self.get_hero() for hero in hero_list: hero_no = str(hero[’ename’]) self.detail_url = hero_no + ‘.shtml’ hero_name = hero[‘cname’] self.get_hero_skin(hero_name, hero_no)# 程序执行入口if name == ‘main’: skin = Skin() skin.run()最后其实思路就是这么简单,当然了,如果有其他思路以及想法的,欢迎留言交流。额,差点忘了,大家有兴趣的,可以尝试一下爬取英雄联盟的所有英雄皮肤高清图片,有其他任何问题,也欢迎留言和交流。 ...

November 8, 2018 · 1 min · jiezi