-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 39 KB
/
content.json
1
{"meta":{"title":"huzai9527's personal blog","subtitle":null,"description":null,"author":"John Doe","url":"http://yoursite.com"},"pages":[{"title":"Tags","date":"2018-11-11T05:38:56.590Z","updated":"2018-11-11T05:38:56.590Z","comments":true,"path":"tags/index.html","permalink":"http://yoursite.com/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"数据分析----数据清洗","slug":"数据分析-数据清洗","date":"2019-01-20T00:03:42.000Z","updated":"2019-01-20T00:05:31.926Z","comments":true,"path":"2019/01/20/数据分析-数据清洗/","link":"","permalink":"http://yoursite.com/2019/01/20/数据分析-数据清洗/","excerpt":"","text":"数据分析—-数据清洗一、导入数据1234import pandas as pdimport numpy as npfrom pandas import Series,DataFrameimport xlrd 12df = DataFrame(pd.read_excel('datas/grades.xlsx')) print(df) Unnamed: 0 Unnamed: 1 Unnamed: 2 Unnamed: 3 0 蒋广佳 43.0 69.0 61.0 1 廖菲 80.0 64.0 62.0 2 沈秀玲 68.0 74.0 98.0 3 韦丹 48.0 53.0 64.0 4 张梦雅 72.0 73.0 96.0 5 赵雅欣 60.0 NaN 70.0 6 曹海广 74.0 60.0 20.0 7 陈泽灿 38.0 21.0 92.0 8 NaN 88.0 67.0 84.0 9 高海亮 86.0 74.0 96.0 10 顾晓冬 84.0 60.0 90.0 11 侯星宇 64.0 111.0 NaN 12 江宜哲 60.0 33.0 70.0 13 NaN NaN NaN NaN 14 梁杨杨 68.0 54.0 94.0 15 刘辉 NaN 63.0 98.0 16 罗嘉豪 39.0 44.0 56.0 17 施亚君 90.0 63.0 90.0 18 孙添 64.0 63.0 78.0 19 王杰 74.0 NaN 76.0 20 王泽 52.0 48.0 94.0 21 NaN 60.0 69.0 74.0 22 杨福程 70.0 49.0 76.0 23 尤澳晨 91.0 67.0 86.0 24 翟佳 78.0 73.0 88.0 25 张旭 100.0 60.0 98.0 26 支星哲 80.0 63.0 100.0 27 邹湘涛 54.0 40.0 90.0 我们可以看见上面的数据是缺少标注的,列名缺少标注;并且有很多是空值,因此我们要对数据进行清洗,提高数据的质量。在这里数据清洗有四个要点简称“完全合一” 完整性:单条数据是否完整,统计的字段是否完善。 全面性:观察某一列的全部数值,选中一列,我们可以看到最大值,最小值,平均值。我们可以通过常识判断数据是否合理,比如:数据定义、单位标识、数值本身。 合法性:数据的类型、内容、大小的合法性。比如数据中存在非ASCII字符,性别存在未知,总分超过100等。 唯一性:数据是否存在重复记录,由于数据来源于不同的渠道,重复的情况是非常常见的。行数据、列数据都需要是唯一的。 事实上数据清洗的标准有差不多七八条,有兴趣的可以了解一下,这里归纳为“完全合一”四条,按照这四条基本上可以解决数据清洗中的大部分问题,使得数据标准、干净、连续。 二、开始数据清洗1、完整性problem 1:空行 solution: 删除 1df.dropna(how=\"all\",inplace=True) problem 2:缺失值 solution: 删除:删除数据缺失的记录 均值:使用当前列的均值 高频:使用当前列出现平率最高的数据 首先我们先把列的标注补上 1df = df.rename(columns={'Unnamed: 0':'index','Unnamed: 1':'math','Unnamed: 2':'english','Unnamed: 3':'c++'}) 1df = df.drop(columns='index') 1print(df) math english c++ 0 43.0 69.0 61.0 1 80.0 64.0 62.0 2 68.0 74.0 98.0 3 48.0 53.0 64.0 4 72.0 73.0 96.0 5 60.0 NaN 70.0 6 74.0 60.0 20.0 7 38.0 21.0 92.0 8 88.0 67.0 84.0 9 86.0 74.0 96.0 10 84.0 60.0 90.0 11 64.0 111.0 NaN 12 60.0 33.0 70.0 14 68.0 54.0 94.0 15 NaN 63.0 98.0 16 39.0 44.0 56.0 17 90.0 63.0 90.0 18 64.0 63.0 78.0 19 74.0 NaN 76.0 20 52.0 48.0 94.0 21 60.0 69.0 74.0 22 70.0 49.0 76.0 23 91.0 67.0 86.0 24 78.0 73.0 88.0 25 100.0 60.0 98.0 26 80.0 63.0 100.0 27 54.0 40.0 90.0 现在我们想对df[‘math’]中缺失的值用平均值代替 1df['math'].fillna(df['math'].mean(),inplace=True) 1print(df) math english c++ 0 43.000000 69.0 61.0 1 80.000000 64.0 62.0 2 68.000000 74.0 98.0 3 48.000000 53.0 64.0 4 72.000000 73.0 96.0 5 60.000000 NaN 70.0 6 74.000000 60.0 20.0 7 38.000000 21.0 92.0 8 88.000000 67.0 84.0 9 86.000000 74.0 96.0 10 84.000000 60.0 90.0 11 64.000000 111.0 NaN 12 60.000000 33.0 70.0 13 68.653846 NaN NaN 14 68.000000 54.0 94.0 15 68.653846 63.0 98.0 16 39.000000 44.0 56.0 17 90.000000 63.0 90.0 18 64.000000 63.0 78.0 19 74.000000 NaN 76.0 20 52.000000 48.0 94.0 21 60.000000 69.0 74.0 22 70.000000 49.0 76.0 23 91.000000 67.0 86.0 24 78.000000 73.0 88.0 25 100.000000 60.0 98.0 26 80.000000 63.0 100.0 27 54.000000 40.0 90.0 如果想用最高频率的数据对english进行填充,可以通过value_counts获取math字段最高频次english_maxf,然后对其进行填充 1english_maxf = df['english'].value_counts().index[0] 1df['english'].fillna(english_maxf,inplace=True) 1print(df) math english c++ 0 43.000000 69.0 61.0 1 80.000000 64.0 62.0 2 68.000000 74.0 98.0 3 48.000000 53.0 64.0 4 72.000000 73.0 96.0 5 60.000000 63.0 70.0 6 74.000000 60.0 20.0 7 38.000000 21.0 92.0 8 88.000000 67.0 84.0 9 86.000000 74.0 96.0 10 84.000000 60.0 90.0 11 64.000000 111.0 NaN 12 60.000000 33.0 70.0 13 68.653846 63.0 NaN 14 68.000000 54.0 94.0 15 68.653846 63.0 98.0 16 39.000000 44.0 56.0 17 90.000000 63.0 90.0 18 64.000000 63.0 78.0 19 74.000000 63.0 76.0 20 52.000000 48.0 94.0 21 60.000000 69.0 74.0 22 70.000000 49.0 76.0 23 91.000000 67.0 86.0 24 78.000000 73.0 88.0 25 100.000000 60.0 98.0 26 80.000000 63.0 100.0 27 54.000000 40.0 90.0 2、全面性problem:列数据单位不统一solution:将不同的单位的找出来,将其进行迭代替换,比如说将榜(lbs)转化为千克(kgs) 12345678# 获取 weight 数据列中单位为 lbs 的数据rows_with_lbs = df['weight'].str.contains('lbs').fillna(False)print df[rows_with_lbs]# 将 lbs 转换为 kgs, 2.2lbs=1kgsfor i,lbs_row in df[rows_with_lbs].iterrows(): # 截取从头开始到倒数第三个字符之前,即去掉 lbs。 weight = int(float(lbs_row['weight'][:-3])/2.2) df.at[i,'weight'] = '{}kgs'.format(weight) 3、合理性problem:非ASCII字符solution:对于非ASCII字符,我们可以采用删除或者替换的方式,我们直接选择删除 1df['name'].replace({r'[^\\x00-\\x7f]+':''},regex=True,inplace=True) 4、唯一性problem1:一列有多个参数solution:比如英文名字,是有两部分组成的,包含两个参数Firstname、Lastnamr,我们需要将name一列拆分为Firstname和Lastname两个字段,我们可以采用split方法,对其进行切分 12df['First_namr','Last_name'] = df['name'].str.split(expand=True)df.drop('name',axis=1,inplace=True) problem2:重读数据solution:我们校验数据是否存在重复数据,如果有重复数据,如果就用pandas提供的drop_duplicates()来删除重复数据。 1df.drop_duplicates(['First_name','Last_name'],inplace=True)","categories":[],"tags":[{"name":"数据分析","slug":"数据分析","permalink":"http://yoursite.com/tags/数据分析/"}]},{"title":"爬取网易云热评并生成词云","slug":"爬取网易云热评并生成词云","date":"2019-01-12T02:06:39.000Z","updated":"2019-01-19T10:11:35.682Z","comments":true,"path":"2019/01/12/爬取网易云热评并生成词云/","link":"","permalink":"http://yoursite.com/2019/01/12/爬取网易云热评并生成词云/","excerpt":"","text":"分析热评的请求URL 首先我们先对请求抓包,发现所有的评论都包含在 https://music.163.com/weapi/v1/resource/comments/R_SO_4_32785700?csrf_token="里面,然后再去分析这个请求,发现这是一个POST请求,请求参数由两个params以及encSecKey。好了到此我们需要的东西都有了,接下来我们分析如何去得到这两个参数。 找到请求 分析请求参数 分析js加密 找到全局js文件,找到两个参数所在的位置 发现这两个参数是由window.asrsea获得的,接着去定位到这个函数找到对应的原函数d 对js进行调试,发现d的四个参数,有三个是定值,这个函数还用到了a、b、c三个函数 其中a是产生一个16位的随机数(这里我直接让它等于FwtEYduOXlNEHbLP)为什么要等与这个呢 hhh 因为我发现这个随机数,他在生成encText的时候用了一次,生成encSecKey的时候,又用了一次,而且encSecKey就只跟这个随机数相关,所以让这个随机数为定值的话,就可以直接得到encSecKey的值,不用再去搞一个rsa加密,为了让你们看清楚,我还是把贴出来把 b函数就是我们主要要解决的AES加密,经过调试,我们可以知道它的两个参数a、b分别是加密字符转、密钥。以及AES的偏移量为0102030405060708、加密模式为CBC 接下来看c函数,c函数其实是RSA加密,获取encSecKey的值的他的三个参数,只有a是变量,是我们随机生成的16为随机数,这里我们就默认为定值,b、c应该是和rsa加密有关的参数,应为本身并没有学过加密,这里我就不多说了,但是经过调试,我们可以知道b、c是定值 b =010001 c是一大串字符串。见下图。 最后我们具体分析一下d函数,经过N次调试,我发现这其实和我的想法差不多,h是一个字典,包含了我们需要的两个参数。encText是由两次AES加密产生的及两次b,加密字符串是一样的,然后密钥第一次是个定值0CoJUm6Qyw8W8jud,第二次是16位随机数,也相当于定值。所以encText就出来了,params是由一次RSA加密产生的,并且只与16位的随机数有关,这里就清楚为什么我让随机数直接等于FwtEYduOXlNEHbLP,哈哈。因为我调试的时候,刚好出现了这么个随机数,于是我就直接拿过来用了,这个随机数对应的encSecKey = 81e7a41af9830200d5606be1a632e57eb0006b3cdae579127115c6323d4c4802f3af9efcee21d9f4126dde266773cbd795f19ae44028f9f8d038cd62d2816952fa99bb61ecb5fba87d5b178ff4b982ee34c7491808f7cb774554a0235a210caf2e5e867a0e2ebdf6f994be1b198ab43b14ce1f7cfa6f80b9070dea5fc5d6c712 用python重写js加密 经过js加密码的分析,我用python实现了一下AES加密,具体代码如下,包含两个参数,一个是需要加密的字符串,一个是密钥具体如下 1234567def AES_encrypt(text, key): pad = 16 - len(text) % 16 text = text + pad * chr(pad) encryptor = AES.new(key, AES.MODE_CBC, \"0102030405060708\") encrypt_text = encryptor.encrypt(text) encrypt_text = base64.b64encode(encrypt_text) return encrypt_text 两次调用这个函数。得到结果与调试的结果对比,一模一样。哈哈,上代码、上图 1234f_key = \"0CoJUm6Qyw8W8jud\"text = \"{\\\"rid\\\":\\\"R_SO_4_32785700\\\",\\\"offset\\\":\\\"20\\\",\\\"total\\\":\\\"true\\\",\\\"limit\\\":\\\"20\\\",\\\"csrf_token\\\":\\\"\\\"}\"rs = AES_encrypt(text, f_key)params = AES_encrypt(str(rs)[2:-1], \"FwtEYduOXlNEHbLP\") 这里解释一下,text是我进过N次调试得出的,因为在请求评论之前,text有好几个值来验证其他的东西,这里我大概理解了一下text的含义,这里我们只要知道offset是偏移量,limit是每次请求多少条,比如你请求前二十条则offset=0,limit = 20,我上面的是请求20-40条。 然后直接获取的encSecKey直接赋值就好啦,结合这两个参数,我们的请求参数就构造好了,直接POST吧,就能得到评论啦,哈哈,上代码,上图 1234567891011121314 data = { 'params': params, 'encSecKey': encSecKey}headers = { 'Accept-Language':\"zh-CN,zh;q=0.9,en;q=0.8\", 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36', 'Cookie': 'appver=1.5.0.75771', 'Referer': 'http://music.163.com/'}url = \"https://music.163.com/weapi/v1/resource/comments/R_SO_4_32785700?csrf_token=\"raw = requests.post(url,headers=headers, data=data)print(raw.json()) 解析json,获取评论","categories":[],"tags":[]},{"title":"git简单指令","slug":"git简单指令","date":"2018-12-25T01:02:58.000Z","updated":"2018-12-25T01:50:59.029Z","comments":true,"path":"2018/12/25/git简单指令/","link":"","permalink":"http://yoursite.com/2018/12/25/git简单指令/","excerpt":"","text":"git简单指令首先放一张学习路线 1、创建版本库123mkdir huzai //创建一个空目录cd huzai //进入此目录git init //初始化git仓库 2、添加文件到版本库12git add file //将文件添加到缓存区git commit -m \"post message\" //提交并附带提交信息 3、版本回退123git reset --hard HEAD^ //HEAD是一个指针,指向当前的版本,^代表上一代版本,HEAD^^代表上两代git reflog //查询每次提交的commit_idgit reset --hard commit_id //根据id进行回退 4、管理修改1git diff HEAD -- file //查看工作区(file)与最新版本(HEAD)的区别 5、撤销修改1234git checkout -- file //直接丢弃工作区的修改(可用于恢复误删的文件)//对于已经添加到缓存的修改git reset HEAD file //撤销缓存区的修改git checkout -- file 6、删除文件123rm file //删除本地文件git rm file //删除版本库中的文件git commit -m \"post delete\" //提交删除事务 7、连接远程仓库1234567//先生成连接密钥ssh-kengen -t rsa -C username//将id_rsa.pub中的内容复制到github的密钥管理中//再根据github的提示将本地仓库与远程仓库进行关联git remote add origin [email protected]:username/repository//再推送master分支的所有内容到远程仓库git push -u origin master 8、从远程仓库进行下载1git clone [email protected]:username/repository 9、创建新的分支并切换到该分支下123git checkout -b branchname //创建并切换git branch branch_name //创建git checkout branch_name //切换 10、合并指定分支到当前分支1git merge branch_name 11、删除分支1git branch -d branch_name 12、如果合并时出现冲突12cat conflic_filename//git 会用<<<<< ===== >>>>>>显示不同分支的内容,你则需要手动解决冲突 13、分支管理策略master分支应该是非常稳定的,也就是用于发布最新版本的,平时不应该在上面干活,干活都应该在dev分支上也就是说dev分支是不稳定的,到了某个时候将dev分支合并到master分支上,你和你的小伙伴应该在各自的分支上干活,然后推送到dev分支上 14、bug分支1234git add now_filegit stash //保护现场//这里修改buggit stash pop //提取现场,继续工作 15、丢弃一个没有被合并的分支1git branch -D branch_name 16、多人协作 1、尝试git push origin branch_name 2、如果推送失败,说明远程分支比你的版本新,则你git pull 拉取远程文件 3、合并你两的分支,如果有冲突则手动解决问题 4、重复1 注:如果git pull 提示 no tracking information 则说明远程分支和本地分支没有关联用下面的命令进行关联1git branch --set-uostream-to branch_name origin/branch_name 或者你不知道有什么分支123git remote -v //查看远程仓库的信息git checkout -b branch_name origin/branch_name //创建本地分支以及远程分支git branch --set-upstream-to branch_name origin/branch_name //进行关联","categories":[],"tags":[{"name":"git","slug":"git","permalink":"http://yoursite.com/tags/git/"}]},{"title":"数据分析-pandas","slug":"数据分析-pandas","date":"2018-12-25T00:21:06.000Z","updated":"2018-12-25T00:31:28.682Z","comments":true,"path":"2018/12/25/数据分析-pandas/","link":"","permalink":"http://yoursite.com/2018/12/25/数据分析-pandas/","excerpt":"","text":"数据分析—-pandas核心数据结构 Series & DataFrame123import pandas as pdimport numpy as npfrom pandas import Series, DataFrame Series是一个定长的字典序列,它有两个基本属性index 、 value index 默认是 0 ,1,2,3 递增的,也可以自己指定索引 index=[‘a’, ‘b’, ‘c’]创建Series的三种方式1234567x1 = Series([1,2,3,4])x2 = Series(data=[1,2,3,4],index=['a','b','c','d'])dic = {'a':1,'b':2,'c':3,'d':4}x3 = Series(dic)print(x1)print(x2)print(x3) 0 1 1 2 2 3 3 4 dtype: int64 a 1 b 2 c 3 d 4 dtype: int64 a 1 b 2 c 3 d 4 dtype: int64 DataFrame类似数据库中的表,可以将其看成是由有相同的索引的Series组成创建DataFra几种方式123data = {\"chinese\":[90,80,70,60,50],'math':[70,80,70,90,60],'english':[30,50,70,80,60]}df1 = DataFrame(data=data,index=['zhangfei','guanyu','zhaoyun','huangzhong','machao'])print(df) chinese english math zhangfei 90 30 70 guanyu 80 50 80 zhaoyun 70 70 70 huangzhong 60 80 90 machao 50 60 60 123import xlrddf2 = DataFrame(pd.read_excel('datas/grades.xlsx'))df2 = df2.drop_duplicates() 1print(df2) 姓名 高数 英语 C++ 0 蒋广佳 43 69 61 1 廖菲 80 64 62 2 沈秀玲 68 74 98 3 韦丹 48 53 64 4 张梦雅 72 73 96 5 赵雅欣 60 63 70 6 曹海广 74 60 20 7 陈泽灿 38 21 92 8 邓杰 88 67 84 9 高海亮 86 74 96 10 顾晓冬 84 60 90 11 侯星宇 64 69 96 12 江宜哲 60 33 70 13 李洪汀 76 56 84 14 梁杨杨 68 54 94 15 刘辉 68 63 98 16 罗嘉豪 39 44 56 17 施亚君 90 63 90 18 孙添 64 63 78 19 王杰 74 60 76 20 王泽 52 48 94 21 徐孟圆 60 69 74 22 杨福程 70 49 76 23 尤澳晨 91 67 86 24 翟佳 78 73 88 25 张旭 100 60 98 26 支星哲 80 63 100 27 邹湘涛 54 40 90 数据清洗删除不必要的行或列123#删除行df2 = df2.drop(columns=['姓名'])print(df2) 高数 英语 C++ 0 43 69 61 1 80 64 62 2 68 74 98 3 48 53 64 4 72 73 96 5 60 63 70 6 74 60 20 7 38 21 92 8 88 67 84 9 86 74 96 10 84 60 90 11 64 69 96 12 60 33 70 13 76 56 84 14 68 54 94 15 68 63 98 16 39 44 56 17 90 63 90 18 64 63 78 19 74 60 76 20 52 48 94 21 60 69 74 22 70 49 76 23 91 67 86 24 78 73 88 25 100 60 98 26 80 63 100 27 54 40 90 123#删除列df2 = df2.drop(index = [27])print(df2) 高数 英语 C++ 0 43 69 61 1 80 64 62 2 68 74 98 3 48 53 64 4 72 73 96 5 60 63 70 6 74 60 20 7 38 21 92 8 88 67 84 9 86 74 96 10 84 60 90 11 64 69 96 12 60 33 70 13 76 56 84 14 68 54 94 15 68 63 98 16 39 44 56 17 90 63 90 18 64 63 78 19 74 60 76 20 52 48 94 21 60 69 74 22 70 49 76 23 91 67 86 24 78 73 88 25 100 60 98 26 80 63 100 重命名列名1df2 = df2.rename(columns={'高数':'math','英语':'english'}) 去除重复的值1df2 = df2.drop_duplicates() 更改数据格式12df2['math'] = df2['math'].astype('str')#df2['math'].astype(np.int64) 清除数据间的空格12df2['math'] = df2['math'].map(str.strip) #删除左右两边的空格df2['math'] = df2['math'].map(str.lstrip) #删除左边的空格(str.rstrip 右边的空格) 删除指定字符1df2['math'] = df2['math'].str.strip('$') 大小写转换1df2.columns = df2.columns.str.upper() #全部大写(lower()全部小写 title()首字母大写) 1df2 .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } MATH ENGLISH C++ 0 43 69 61 1 80 64 62 2 68 74 98 3 48 53 64 4 72 73 96 5 60 63 70 6 74 60 20 7 38 21 92 8 88 67 84 9 86 74 96 10 84 60 90 11 64 69 96 12 60 33 70 13 76 56 84 14 68 54 94 15 68 63 98 16 39 44 56 17 90 63 90 18 64 63 78 19 74 60 76 20 52 48 94 21 60 69 74 22 70 49 76 23 91 67 86 24 78 73 88 25 100 60 98 26 80 63 100 使用apply函数对数据进行清洗123#df2['MATH'] = df2['MATH'].apply(str.lower)df2['MATH'] = df2['MATH'].astype(np.int64)df2 .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } MATH ENGLISH C++ 0 43 69 61 1 80 64 62 2 68 74 98 3 48 53 64 4 72 73 96 5 60 63 70 6 74 60 20 7 38 21 92 8 88 67 84 9 86 74 96 10 84 60 90 11 64 69 96 12 60 33 70 13 76 56 84 14 68 54 94 15 68 63 98 16 39 44 56 17 90 63 90 18 64 63 78 19 74 60 76 20 52 48 94 21 60 69 74 22 70 49 76 23 91 67 86 24 78 73 88 25 100 60 98 26 80 63 100 1234def plus(df): df['Total'] = df['MATH']+df['ENGLISH']+df['C++'] return dfdf2 = df2.apply(plus,axis=1) 1print(df2) MATH ENGLISH C++ Total 0 43 69 61 173 1 80 64 62 206 2 68 74 98 240 3 48 53 64 165 4 72 73 96 241 5 60 63 70 193 6 74 60 20 154 7 38 21 92 151 8 88 67 84 239 9 86 74 96 256 10 84 60 90 234 11 64 69 96 229 12 60 33 70 163 13 76 56 84 216 14 68 54 94 216 15 68 63 98 229 16 39 44 56 139 17 90 63 90 243 18 64 63 78 205 19 74 60 76 210 20 52 48 94 194 21 60 69 74 203 22 70 49 76 195 23 91 67 86 244 24 78 73 88 239 25 100 60 98 258 26 80 63 100 243 pandas中常用的统计函数 1print(df2.describe()) MATH ENGLISH C++ Total count 27.000000 27.000000 27.000000 27.000000 mean 69.444444 59.703704 81.148148 210.296296 std 16.113380 12.406000 17.933003 34.410212 min 38.000000 21.000000 20.000000 139.000000 25% 60.000000 55.000000 72.000000 193.500000 50% 70.000000 63.000000 86.000000 216.000000 75% 80.000000 68.000000 95.000000 239.500000 max 100.000000 74.000000 100.000000 258.000000 12","categories":[],"tags":[{"name":"数据分析","slug":"数据分析","permalink":"http://yoursite.com/tags/数据分析/"}]},{"title":"数据分析----numpy ","slug":"数据分析-numpy","date":"2018-12-22T23:21:29.000Z","updated":"2018-12-22T23:22:04.940Z","comments":true,"path":"2018/12/23/数据分析-numpy/","link":"","permalink":"http://yoursite.com/2018/12/23/数据分析-numpy/","excerpt":"","text":"数据分析—numpy12import pandas as pdimport numpy as np 创建普通数组12a = np.array([1,2,3])b = np.array([[1,2,3],[4,5,6],[7,8,9]]) 1b[1,1] = 10 1234print(a.shape)print(b.shape)print(a.dtype)print(b) (3,) (3, 3) int64 [[1 2 3] [4 5 6] [7 8 9]] 创建结构数组1234567personalType = np.dtype({ 'names':['name','age','chinese','math','english'], 'formats':['S25','i','i','i','f']})students = np.array([(\"huzai\",22,99,99,99.5),(\"huzai\",22,99,99,99.5)],dtype=personalType)age = students[:]['age']print(np.mean(age)) 22.0 1print(students) [(b'huzai', 22, 99, 99, 99.5) (b'huzai', 22, 99, 99, 99.5)] 创建连续数组12x1 = np.arange(1,11,2) #步长为2,从1开始的等差数组(不包括终值)x2 = np.linspace(1,9,5) #将1-9分成5块,结果如上 12print(x1)print(x2) [1 3 5 7 9] [1. 3. 5. 7. 9.] 数组间的算数运算1234print(np.add(x1,x2))print(np.subtract(x1,x2))print(np.multiply(x1,x2))print(np.divide(x1,x2)) [ 2. 6. 10. 14. 18.] [0. 0. 0. 0. 0.] [ 1. 9. 25. 49. 81.] [1. 1. 1. 1. 1.] 统计函数数组中的最值 np.amin() amax()1234a = np.array([[1,3,7],[2,5,8],[6,4,9]])print(np.amin(a))print(np.amin(a,0)) #每一列的最小值print(np.amin(a,1)) #每行的最小值 1 [1 3 7] [1 2 4] 统计最大值与最小值之差 ptp()123print(np.ptp(a))print(np.ptp(a,0)) #每列最大值与最小值的差print(np.ptp(a,1)) #每行最大值与最小值的差 8 [5 2 2] [6 6 5] 统计数组的百分位数 percentile(a, p, axis) a:数组名 p 代表百分比 axis代表是行还是列123print(np.percentile(a,50))print(np.percentile(a,50,0))print(np.percentile(a,50,1)) 5.0 [2. 4. 8.] [3. 5. 6.] 统计数组中的中位数以及平均数 median() mean()123print(np.median(a))print(np.median(a,0))print(np.median(a,1)) 5.0 [2. 4. 8.] [3. 5. 6.] 数组中的加权平均值 average(a,weights)1234b = np.array([1,2,3,4])wts = np.array([1,2,3,4])print(np.average(b))print(np.average(b,weights=wts)) 2.5 3.0 统计数组中的标准差(std())与方差(var())12print(np.std(b))print(np.var(b)) 1.118033988749895 1.25 Numpy排序123print(a)print(np.sort(a))print(np.sort(a,0)) [[1 3 7] [2 5 8] [6 4 9]] [[1 3 7] [2 5 8] [4 6 9]] [[1 3 7] [2 4 8] [6 5 9]] 作业题123456st_type = np.dtype({ 'names':['name','chinese','english','math'], 'formats':['S25','i','i','i']})grades = np.array([('zhangfei',66,65,30),('guanyu',95,85,98),('zhaoyun',93,92,96),('huangzhong',90,88,77), ('dianwei',80,90,90)],dtype=st_type) 1print(grades) [(b'zhangfei', 66, 65, 30) (b'guanyu', 95, 85, 98) (b'zhaoyun', 93, 92, 96) (b'huangzhong', 90, 88, 77) (b'dianwei', 80, 90, 90)] 1234chinese = grades[:]['chinese'] english = grades[:]['english']math = grades[:]['math']total = np.add(chinese,english,math) 1print(total) [131 180 185 178 170] 1c_a,e_a,m_a = np.average(chinese),np.average(english),np.average(math) 1print(c_a) 84.8 12","categories":[],"tags":[{"name":"数据分析","slug":"数据分析","permalink":"http://yoursite.com/tags/数据分析/"}]},{"title":"小说更新后发送邮箱的问题解决","slug":"小说更新后发送邮箱的问题解决","date":"2018-11-23T08:54:00.000Z","updated":"2018-11-23T09:44:53.236Z","comments":true,"path":"2018/11/23/小说更新后发送邮箱的问题解决/","link":"","permalink":"http://yoursite.com/2018/11/23/小说更新后发送邮箱的问题解决/","excerpt":"","text":"遇到的问题 先上一张图,看一下问题在哪 从图上我们可以看到,虽然小说是每天发两次给我,但是有时候会漏掉一章,有时候又会重复发一章,这都是小说作者不按时更新惹的祸啊!!!既然小说作者的习惯改变不了,那就完善自我吧! 新的思路,加一个“缓存”缓存是什么意思呢? 本地建一个名为origin.txt的文本文件,每次爬取完成后与origin.txt里面的内容对比一下。 如果一样则不发送。 如果不一样就发送,并且将最新的内容保存到origin.txt文件中,作为下一次的对照。 演示效果 再origin.txt里写入test,然后启动我们可以看到,origin文件已被重新写入,并且新的文本已经发送到邮箱 再次启动,也就是还没跟新的情况我们看到,提示消息,这里不会跟新origin,也不会发送邮件 还遗留的问题 如果作者一下爆发怎么办(一分钟更新十章!)思考一下,其实原理差不多,缓存大小不同罢了!有兴趣的可以尝试一下!项目源码已发布在githubhttps://github.com/huzai9527/fictionSend","categories":[],"tags":[{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"c++指针问题","slug":"c-指针问题","date":"2018-11-19T08:27:20.000Z","updated":"2018-11-19T12:23:15.924Z","comments":true,"path":"2018/11/19/c-指针问题/","link":"","permalink":"http://yoursite.com/2018/11/19/c-指针问题/","excerpt":"","text":"指针究竟是什么 指针是一类特殊的变量,他保存的不是一般数据的值,而是程序中另一对象在内存中的地址我们先通过一个小程序看一看指针如何工作1234567891011#include <iostream>using namespace std;int main(){ int n = 123,m = 456; int *p = &n; cout<<\"&n:\"<<&n<<endl; cout<<\"&p:\"<<&p<<endl; cout<<\" p:\"<<p<<endl; cout<<\"*p:\"<<*p<<endl; return 0;} 从运行结果可以看出下面几点: p本身是有一个地址的且地址为 &p p的值是另一个变量n的地址 &n *p所表示的意思是地址为 p 的内存中所存的值 n 即本段程序中共涉及到2个地址,一个是 n 的地址,一个是 p 的地址,我们用一张图来表示他们的关系指针的初始化 被具有相同类型的对象初始化 12int i = 10;int *p = &i; 由另一个同一类型的指针初始化,这时两个指针指向同一地址空间 1int *p1 = p; 通过直接分配内存地址得到初值 1int *p2 = new int; 指针也可以没有类型,通用指针的定义,这样的指针可以指向任一对象 1void *p3 指针的运算符定义指针的目的事通过指针变量间接的访问变量 *:取指针值运算符。通过指针所指内存单元的地址间接的访问对应的存储单元。若指针变量p指向变量a,则 *p的运算结果为变量a的值 &:取地址运算符。返回变量对应的存储单元地址,若a为int变量,p为int型指针变量,则 p = &a表示将a的存储单元地址赋给p。用一个程序验证一下: 12345678910111213#include <iostream>using namespace std;int main(){ int a = 100; int *p,*p1,*q; p = &a; p1 = p; q = NULL; cout<<\"a=\"<<a<<\",\"<<\"*p=\"<<*p<<\",\"<<\"p=\"<<p<<endl; *p1 = 200; cout<<\"a=\"<<a<<\",\"<<\"*p=\"<<*p<<\",\"<<\"p=\"<<p<<endl; cout<<\"*p1=\"<<*p1<<\",\"<<\"p1=\"<<p1<<endl;} 运行结果 指针与数组的关系 数组名和指针在引用数组元素和取他们的地址方面可以相互转换,但两者有一个重要的不同点 数组是在定义时就分配好内存空间的,因此数组名是一个地址常量,在程序中不能将数组名作为变量为其赋值,而指针是一个变量,可以多次赋值我们通过一个程序看一下他们的关系 1234567891011121314#include <iostream>using namespace std;int main(){int a[10]={1,2,3,4,5,6,7,8,9,10};int *pa = a;int i = 3;cout<<\"a[i] :\"<<a[i]<<endl;cout<<\"*(pa+i):\"<<*(pa+i)<<endl;cout<<\"*(a+i) :\"<<*(a+i)<<endl;cout<<\"&a[i] :\"<<&a[i]<<endl;cout<<\"a+i :\"<<a+i<<endl;cout<<\"pa+i :\"<<pa+i<<endl; } 运行结果 易重要的和易混淆的概念 为什么要对指针初始化?定义了指针变量后,系统会为其分配一个内存空间,若没有赋值则此内存区域的内容是随机的,也就是指针随机指向一个内存单元。你想想如果你对一个随机的内存空间进行写操作,会怎样! 指针的运算指针 + 整数 = 指针指针 - 指针 = 整数 //同类行的指针相减表示两个基类型变量的个数指针 + 指针 = ???? //不可以 new、 new[]、 delete、 delete[]有什么区别 1234int *p = new int(3) // 为p分配了一个整形变量的存储区域并初始化为3int *p1 = new int[20] // 分配20个整形变量的区域给p1delete p //释放有new申请的空间delete[] p1 //释放由new[]申请的空间 c++程序中动态分配的内存不会被自动释放 指针函数和函数指针含义相同吗?完全不同!指针函数:若一个函数返回的是一个地址,则称该函数为指针函数。格式是 数据类型 函数名(参数列表)函数指针:指针变量指向一个函数的入口地址,格式为 数据类型 (函数指针变量)(参数列表)函数指针的用法:12345678910111213141516#include <iostream>using namespace std;int cul(int (*pf)(int,int), int x, int y){ return pf(x,y);}int add(int x,int y){ return x+y;}int sub(int x,int y){ return x-y;}int main(){ int a=10,b=20; cout<<a<<\"+\"<<b<<\"=\"<<cul(add,a,b)<<endl; cout<<a<<\"-\"<<b<<\"=\"<<cul(sub,a,b);} 常量指针、指针常量、指向常量的指针常量有什么区别常量指针:表示指针指向的是一个常量,格式:const 类型 指针变量 或 类型 const 指针变量1234int i;const int *p = &i;*p = 10; //错误i = 10; //正确 指针常量:表示所定义的指针是一个常量,只能在定义的时候初始化123int i,j;int * const p = &i;p = &j;//错误 指向常量的指针常量:格式为 const 类型 * const 指针常量12345int i,j;const int * const p = &i;*p = 10;//错误p = &j;//错误i = 10;//正确","categories":[],"tags":[{"name":"c++","slug":"c","permalink":"http://yoursite.com/tags/c/"}]},{"title":"scrapy构建自己的ip代理池","slug":"scrapy构建自己的ip代理池","date":"2018-11-18T09:33:13.000Z","updated":"2018-11-19T08:15:02.296Z","comments":true,"path":"2018/11/18/scrapy构建自己的ip代理池/","link":"","permalink":"http://yoursite.com/2018/11/18/scrapy构建自己的ip代理池/","excerpt":"","text":"用scrapy爬取可用的代理分析免费代理网站的结构 我爬取了三个字段:IP、port、type分析要爬取的数据,编写items.py 因此在items.py中,建立相应的字段1234567import scrapyclass IproxyItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() ip = scrapy.Field() type = scrapy.Field() port = scrapy.Field() 爬取所有的免费ip 在spider目录下,创建IpSpider.py12345678910111213import scrapyimport Iproxy.itemsclass IpSpider(scrapy.Spider): name = 'IpSpider' allowed_domains = ['xicidaili.com'] start_urls = ['http://www.xicidaili.com/'] def parse(self, response): item = Iproxy.items.IproxyItem() item['ip'] = response.css('tr td:nth-child(2)::text').extract() item['port'] = response.css('tr td:nth-child(3)::text').extract() item['type'] = response.css('tr td:nth-child(6) ::text').extract() yield item 检测是否可用,如果可用则存入数据库 因为是免费的ip,所以我们有必要检测一下他是否可用,对于可用的就存入数据库,反之则丢弃 检测处理数据在pipeline.py中编写 检测原理,通过代理访问百度,如果能够访问,则说明可用1234567891011121314151617181920212223242526272829303132333435363738394041# -*- coding: utf-8 -*-# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.htmlimport pymysqlimport requestsclass IproxyPipeline(object): def process_item(self, item, spider): print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') db = pymysql.connect(\"localhost\", \"root\", \"168168\", \"spider\") cursor = db.cursor() for i in range(1, len(item['ip'])): ip = item['ip'][i] + ':' + item['port'][i] try: if self.proxyIpCheck(ip) is False: print('此ip:'+ip+\"不能用\") continue else: print('此ip:'+ip+'可用,存入数据库!') sql = 'insert into proxyIp value (\"%s\")' % (ip) cursor.execute(sql) db.commit() except: db.rollback() db.close() return item def proxyIpCheck(self, ip): proxies = {'http': 'http://' + ip, 'https': 'https://' + ip} try: r = requests.get('https://www.baidu.com/', proxies=proxies, timeout=1) if (r.status_code == 200): return True else: return False except: return False 运行情况 可以看出还是有好多ip不能用的 可用的存在数据库","categories":[],"tags":[{"name":"python scrapy 爬虫","slug":"python-scrapy-爬虫","permalink":"http://yoursite.com/tags/python-scrapy-爬虫/"}]},{"title":"python爬取最新更新的小说并发送到你的邮箱","slug":"python爬取最新更新的小说并发送到你的邮箱","date":"2018-11-17T07:07:29.000Z","updated":"2018-11-17T08:30:03.635Z","comments":true,"path":"2018/11/17/python爬取最新更新的小说并发送到你的邮箱/","link":"","permalink":"http://yoursite.com/2018/11/17/python爬取最新更新的小说并发送到你的邮箱/","excerpt":"","text":"数据获取—Spider()找目标网站,该网站是你看小说的网站,分析该网站的结构方便你对内容的抓取 这里我获取最新章节的时间、标题以及标题的连接 这里获取内容 编写spider方法,确定他的返回值,这里我返回的是一个list,包括更新的时间、标题、内容 方法中需要导入的包 requests bs4 re 12345678910111213141516171819202122def spider(): list = [] response = requests.get('https://www.xbiquge6.com/13_13134/') response.encoding = ('utf-8') html = response.text html = BeautifulSoup(html, 'html.parser') time = html.select('div#info p:nth-of-type(3)').__getitem__(0).text[5:] title = html.select('div#info p:nth-of-type(4) a[href]').__getitem__(0).text href = html.select('div#info p:nth-of-type(4) a[href]').__getitem__(0) # print(title) pattern = re.compile(r'href=\"(.+?)\"') href = re.findall(pattern, href.__str__()).__getitem__(0) href = \"https://www.xbiquge6.com\" + href response = requests.get(href) response.encoding = ('utf-8') html = BeautifulSoup(response.text, 'html.parser') content = html.select('div#content') # print(content) list.append(title) list.append(content) list.append(time) return list 邮件发送—smtp()首先先在你的邮箱中设置打开smtp服务比如我的QQ邮箱,先进入邮箱->点击设置->点击账户->下滑找到smtp服务->点击开启服务->生成授权码(就是你在smtp方法中用到的password)![PCO_6AO93%@2W$B}GFGHI0 (1).png 编写smtp方法,向我的邮箱发送小说,确定返回值是bool类型,成功为True,失败为False12345678910111213141516def mail(): list = spider(); ret = True try: mail_msg = list.__getitem__(1).__str__() msg = MIMEText(mail_msg, 'html', 'utf-8') msg['From'] = formataddr(['huzai', my_sender]) msg['To'] = formataddr(['huzai', receiver]) msg['Subject'] = list.__getitem__(0) server = smtplib.SMTP_SSL('smtp.qq.com', 465) server.login(my_sender, my_pwd) server.sendmail(my_sender, [receiver], msg.as_string()) server.quit() except Exception: ret = False return ret 上传脚本到服务器使用xftp将写好的smtp.py上传到你的云服务器上直接拖进去就行 这里注意保证你的服务器上的python版本和你本机一致,且需要的包已经安装 如果你的服务器上的版本是2.*的可以运行下面代码安装python3123sudo apt-get remove pythonsudo apt-get install python3sudo apt autoremove 用xshell进入服务器试着运行 在服务器端设置定时执行确保你安装了crontab(ubuntu默认安装)cron命名解析:执行的时间 + 执行的用户 + 执行的命令 查看原有的cron1cat /etc/crontab 编辑你的程序1sudo nano /etc/crontab 编写你的命令,每天14:58给我发送邮件,这里根据你看的小说的更新时间设置,一天几更在大约什么时间等等158 14 * * * root python3 smtp.py 编辑好了再次查看cron是否已经写入,我这里已经写入重启crontab服务1service cron restart 静静的等待14:58的到来,查看邮箱 邮件收到了最新更新的哦","categories":[],"tags":[{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"github+hexo搭建个人博客","slug":"github-hexo搭建个人博客","date":"2018-11-11T09:46:19.000Z","updated":"2018-11-13T12:08:27.276Z","comments":true,"path":"2018/11/11/github-hexo搭建个人博客/","link":"","permalink":"http://yoursite.com/2018/11/11/github-hexo搭建个人博客/","excerpt":"","text":"1.创建的项目名默认为 用户名.github.io,创建时点击生成readme文件,方便后面添加说明 2.在本地创建一个文件夹,我是在E盘创建的blog,推荐用vscode作为编辑器,在编辑器里面打开文件夹,打开Terminer 3.使用hexo初始化文件夹,这一步会产生很多的hexo配置文件,我们先不管,先跑起来 4.运行hexo server打开服务,看看本地能不能显示运行后访问url,如果看到如图就成功了 5.配置文件中填写git的配置信息,按照如下格式填写 6.打开文件夹,右键git bash here 7.输入cd ~/.ssh,进入ssh文件夹 8.配置git中的用户名和邮箱 9.生成ssh密钥 10.在github的项目中加入密钥 11.测试密钥链接是否成功 12.测试成功后再再编辑器中运行hexo clean hexo g hexo d 这样就算上传成功 13.访问你的博客,看到之前再本地运行的界面,就行了","categories":[],"tags":[{"name":"github","slug":"github","permalink":"http://yoursite.com/tags/github/"}]},{"title":"Hello World","slug":"hello-world","date":"2018-11-10T13:00:35.376Z","updated":"2018-11-10T13:00:35.376Z","comments":true,"path":"2018/11/10/hello-world/","link":"","permalink":"http://yoursite.com/2018/11/10/hello-world/","excerpt":"","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[]}]}