Giter VIP home page Giter VIP logo

ucanuupnobb's Introduction

这是什么?

you can you up, no bb.

可能用得上的作业集

跟着以下作业,从0开始,一点点来。

每次作业,最少1天,最多2天。如果难度超纲,可以自行搜索解决,也请给我反馈。

完全0基础,就跟着作业来,刚好完成作业要求即可。时间充裕、精力旺盛,可以超前,自己拓展都OK。很灵活的。

下列内容,只是提供作业,并不是提供教学。主要还是依靠自学、并在兴趣小组中互受鼓舞。

A系列:准备vscode + github,并熟悉git的最少必要操作。

B系列:hello python,极简开始的python编程之旅。

建议记录你在编程这件事上的时间投入,但不做自我评判,单纯记录而已。

保持你对编程的好奇心,并呵护你尝试编程的愿望,比什么都重要。试试玩玩看呗!

如果你已经启动自学,并解决了一些可能对他人有用的“困难”,欢迎写成简明清晰的教程(或具有“输送价值观”的、完整的作品:文章),并向 本项目 发起 pull request。

文件路径: \ucanuupnobb\ourStories\文章标题+你的名字.md

《自学是门手艺》中,哪些值得刻意练习的技能。

  • 采用 google 搜索的技能

  • 正则表达式

  • 刻意思考:这东西我能用在哪儿呢?(这东西,是你正在刻意练习的某个技能)

  • 能 Google 出答案的问题,就不需要去麻烦别人

  • 练习键盘盲打

  • 有自己的完整作品(从写一篇完整的文章开始)

  • 用纸笔罗列整理那些为了做到“全面完整”而必须优先做的事。

  • 用“全面完整”的原则来对抗“注意力漂移”。

  • git(如果学,不如学点高档的)

如果你已经刻意练习了以上技能,欢迎向 这个项目 发起 pull request,添加你的练习记录或者感悟心得。

文件路径: \ucanuupnobb\DeliberatePracticeNotes\技能名+你的名字.md

ucanuupnobb's People

Contributors

liujuanjuan1984 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ucanuupnobb's Issues

如何用vscode更新本仓库?

环境:
1、操作系统:win10
2、软件环境:vscode
3、其它:已把本仓库clone到本地。

操作步骤:
1、启动vscode,通过 terminal - new 启动新的 terminal
或者采用快捷键 ctrl +shift + `

2、进入本地仓库目录
D:\liujuanjuan\vscode\ucanuupnobb
可能使用的命令行:pwd,cd

3、检查更新:

git --help
git status

4、提交更新

git -A
git commit -m "messenge"
git push origin master

【笔记】能写数据后台,需要掌握哪些进阶的sql语句?

国庆假期花了一些时间,首次尝试并玩转 grafana,这几天继续不断优化和完善,如今看着自己的成果,相当满意。——逐步接近我想要的理想后台啦。

需求是不停歇的。今天我又给自己发掘了一些新需求,比如变量、筛选框之类,都收集下来等有空继续玩。编程学习的过程中,对于自己尚未尝试的新技能点,本能直觉会感到困难,但动手经验告诉我:莫慌,用起来就懂了,瞧我自己每次都能很快上手吖。——善于让自己在学习的过程中感受良好,并确实持续进步,自我激励是一个特别实用的软技能。

然后我想着不妨把这几天玩转 grafana 时用到的进阶版的 sql 语句整理出来。所谓进阶版,是针对我个人的 sql 能力啦,确切地讲,是指在我之前的笔记中未曾出现、且玩转 grafana 中我确实反复用到的。整理自己刚刚反复实践的新知识点,能很好地巩固新知。完成这件事,方能安心进入下一个阶段向未知冲刺。

之前写了一篇笔记,记录自己是为什么要玩 grafana ,以及如何在 24 H做到被工程师称赞,文中提及我把工程师已经实现的 sql语句拷贝下来,拆解为元知识点,然后逐个理解:它是什么功能,如何用,然后直接用起来试试效果。

举个实例来拆解元知识点

在本篇笔记中,我也先举一个实例用作知识点拆解,如下,该述语句的作用是:统计每天具有学习行为的用户数。注:学习行为其实包含多种具体的行为,分布在两个表中。

with data as(
  select 
    date(created_at) as time,
    user_id
  from user_comments
  union all
  select 
    date(created_at) as time,
    user_id
  from user_activities
)
select
  time,
  count(distinct user_id) as 每日学习用户数
from data
group by time
order by time

注意:sql 对大小写、换行、缩进之类都不敏感,这是和 python不同的地方。上面之所以要换行和缩进,只是为了易读性。

这一条 sql 语句看着挺长,其实是两个部分。as 前面的 data 是数据的名字,我们自定义的,后面B部分的from 数据源就是它。被 with data as() 括起来的A部分,用于生成数据,相当于先做一次检索统计得到一些数据命名为 data ,然后再对 data 进行检索统计。

with data as (【语句块A】)
【语句块B】

可嵌套的 with data as()

短时间用 with data as() 用的比较多时,我就揣测:这玩意儿能嵌套吗?一试果然可行。嵌套只是让它看上去复杂点,本质没啥变化。如下所示,语句块 A 的数据源是原始数据,语句块 B 的数据源是 data,语句块 C 的数据源是 datax。

with datax as(
    with data as (【语句块A】)
  【语句块B】
 )
    【语句块C】

实战中,我最多用过3层嵌套,且偶尔为之;双层嵌套用的多一些。而单层则相当常用。

union合并数据行

上方实例被 with data as() 括起来的部分,其实是两个表满足条件的数据合并。抽象一下如下。

【语句块X】
union all
【语句块Y】

处理表格数据的合并时,细分有以下三个情形:

  • 把多列或多行的数据,合并为单列或单行的数据
  • 把A表的数列,与B表的数列合并起来
  • 把A表的数行,与B表的数行合并起来

union 处理的是基于行的合并。举例来说,如果语句块X的结果为a行,语句块Y的结果为b行,则通过union all 合并后的结果将有(a+b)行。而用 union 的结果是取a和b的并集,即a、b中都存在的数据行只保留一份。

相对应的,在pandas 通过 pd.concat()axis参数就能处理行、列的不同方式合并,还真是简约吖。

函数data()as别名

上方举例中,语句块X 和Y大体上是蛮基础的语句。但依然出现了我之前没有用过的方法。

  • date(created_at) as time,count(distinct user_id) as 每日学习用户数 这两个片段中,as 之前是表达式语句,as 之后是该语句运算结果的别名。
  • date() 方法是把复杂的时间数据简化为年月日的日期数据。超高频使用。
  • count(distinct user_id) 则表示:对 user_id 去重,然后统计 user_id 个数。超高频使用。

image

类似count()sum()都是高频使用的基础函数。不过数据统计中,更常用到累加。语句是定番组合,就不再单独罗列啦:

sum(兑换用户数) over (order by 兑换日期 asc rows between unbounded preceding and current row) as 累计用户数

count(1)count(*) count(column_name) 在不同情况下,运行效率不同。鉴于我暂时没有写出性能最好的sql语句之觉悟,暂不深究啦。

各种情况下的去重

上面提及distinct ,如何使用distinct 倒不复杂;复杂的是需求,对数据指标的定义要理解准确;不同的数据指标,对去重有不同的要求。

情境A:不去重。

虽然count的是user_id,但这个数据其实并不是每天留言的用户数,而是每天留言的条数。

select 
    date(created_at) as time,
    count(user_id) as 每日留言条数
from
    user_comments
group by
    time
order by
    time

情境B:当日去重。

在当天内去重,跨天不去重。用户在某一天有多条留言,最终也只能为当天留言用户数贡献计数1

select 
    date(created_at) as time,
    count(distinct user_id) as 每日留言用户数
from
    user_comments
group by
    time
order by
    time

情境C:历史累积去重。

有过留言行为的累计用户数,则在全时段内去重。只要该用户曾有过留言行为,则计数1,不再重复计数。

select
  count(distinct user_id) as 留过言的用户总数
from
  user_comments

情境D:每日和历史累积同时去重。

假设我们想知道每日新增的留言用户数,即如果该用户以前曾留言则不计数,否则在首次留言当天计数1,这个情境比前面三种复杂点,但同样相当高频使用。

with data as (  
  select 
    distinct on (user_id) user_id, 
    date(created_at) as time
  from 
    user_comments
)
  
select 
  time,
  count(user_id) as 每日新增留言用户数,
  count(user_id) over (order by time asc rows between unbounded preceding and current row)  as 累积留言用户总数 
from data 
group by time,user_id
order by time

几个常见的小知识点

limit指定显示多少条数据。换言之,没有这个条件,就表示要显示查询结果的所有数据。我之前不知道这个知识点时,有时不小心直接在命令行提示符中查看某个表,会一下子打印很多很多行,以至于一直下翻都不见底……而在数据后台中,通常配合排序功能,用来显示“排行榜”数据。比如,学习次数排行榜、兑换总额排行榜之类。

select *  from table_name limit 50;

image

order by 指定数据按哪些字段排序,默认顺序,可用desc倒序。

select *  from table_name order by column_name;

image

group by 指定数据按哪些字段分组,很多报表按日统计。前面举例中无形中也用了该方法数次,就不单独举例啦。

多表联合查询

最后说明下,相对复杂的多表查询。从多个表格、或表格和自定义数据源如data中合并查询。一个相对简单的实例如下,根据输入变量 user_name 从 users_extra 查询到 user_id,然后用 user_id 去user_activities 表查询。

with data as(
  select user_id,user_name from users_extra where user_name = '$user_name'
)
select
  count(1) as 学习行为次数
from 
  user_activities,data
where
  user_activities.user_id = data.user_id

这种联合查询必要的条件是,多个数据源可以通过某个字段对应起来。更复杂的例子,其实都可以动用拆解的方式,拆解为更单元的知识点。这里就不展开啦。

顺便说,上面的 user_name = '$user_name' 语句是 grafana 中用于调用自定义变量,实现后可支持下拉框筛选。这也是刚开始写这篇文章时,我提到的新需求,结果文章修修改改写完,这个需求竟然被我实现了。还真是快!
image

小结

如果某天你和我一样开始接触一点进阶、复杂的sql语句或其它技能,千万别慌,找一些现成的实例(比如收藏我这篇笔记)来消化,逐块拆解为元知识点,然后再把它们拼装结合用起来,你会发现:也不过如此嘛。

这个过程多像玩儿积木吖!好玩好玩!

如果这篇笔记帮到了你,一定要留言告诉我吖;这将鼓励我整理和分享更多。

24H玩转 Grafana 被工程师称相当专业,如何做到?

国庆假期发生了两件小事,其一是我默默度过 35 周岁生日,其二是玩了下 grafana `并在节后第一天被工程师 M 称赞:相当专业。

1、我为什么要玩 grafana 呢?

数月前我提交了一份数据后台需求给工程师 M,他选用和部署了 grafana 这个第三方开源的工具,仅用两三天就完成了这份需求。这效率相当快,令我对 M 和 grafana 印象深刻。但我仍不满足,M提交的成品所有数据都图形化的而我更想要表格样式的数据。为了进一步整合其它数据进行统计分析,我还需手动导出数据,并写了复杂的 python 脚本用 pandas 做统计分析,每周至少运行一次。我常常冒出新的数据需求,它们并不大,但走一遍需求评审、排期开发验收的流程,似乎还挺麻烦的。

这些都还只算铺垫,真正的导火索是国庆假期前的 sprint 总结会上提及我们几个产品的数据将整合到 grafana 统一实现。 CTO 曾对我提及如果我懂些 sql 语句,可以自己写。——哈?我懂点 sql 语句的吖,这不刚整理了一份笔记《【总结】python如何与mysql实现交互及常用sql语句》嘛。我处于 “sql 不过如此,放马过来啊”的大无畏状态-_-||

国庆假期来了,那就玩玩儿看呗。

2、短时间如何上手 grafana

M之前为了开发我的需求,已经完成了 grafana 的部署,并设置好了数据源。这次他专门创建了一个练习用的 dashboard 并开通编辑权限给我。特别说明,我的编辑权限仅有数据源的查询权,没有增删改的权限,这对数据源是安全的。另外,M 已有的实现也让初次上手的我可以照葫芦画瓢。这些是
我比完全零准备的 grafana 新手占便宜的地方。

我并不想把 M 已经开发的需求重新实现一遍,我想要实现自己的数据需求。——想要什么数据,以什么样式呈现,我脑子里的需求俯拾即是。

学习过程具体分为三个部分:

  • A:熟悉和了解 grafana 在 dashboard 上如何添加、编辑图表等模块,就是了解这个工具如何使用。
  • B:熟悉和了解 数据源(我们产品的数据库),有哪些表,有哪些字段之类。
  • C:实现数据需求的 sql 语句该如何写。

A 部分,搜了两篇 grafana 如何使用之类的文章,大概浏览下即可。总是照着别人整理的步骤图按部就班,学习体验不好。大部分时候,我都是直接鼓捣。这种开源的可视化的工具,自己尝试一下就能快速熟悉起来。

B 部分,当个伸手党,让工程师帮忙把所有表格 describe 导出也 OK 的;M给我的是一份表格的类定义文件。通过 A 部分的探索,我很快发现,在 dashboard 上创建一个模块,如果选择折线图类型,sql 语句编辑区可以任人挑选表格名称,这样有哪些数据表格就清楚了;如果选择表格类型,并使用select * from table_name limit 50 ,就能呈现该表的部分数据,这样该表格有哪些字段也就清楚了。

C 部分,我把 M 之前实现的 sql 语句单独拷贝到 jupyter notebook 里,自己拆解为更基础的知识点,然后一点点熟悉了解。一个小技巧是,对于新手来说 sql 语句的易读相当重要,能直接降低复杂度。所以我采用 markdown 语法如下,语法呈现就很清晰了:
image

以上三个部分无需按顺序进行。自己对哪个模块更感兴趣,就先开始哪个;过程中也可交叉轮换进行。接下来就是通过实现自己的数据需求,反复重复巩固并深入 以上 3 个部分,直至产生令自己满意的产出。为此投入的时间开销24~48H 足够啦,完全不耽误假期陪家人、睡懒觉、看电影。

image

3、对职场分工保持清醒

最后需要强调一下,我很清楚自己并不想要取代工程师完成数据后台的开发。比如:
1、一些复杂需求,我自己写sql,很难,学起来也慢。这些我会陆续收集罗列出来,走排期,请工程师帮忙,不会自己硬钻进去。
2、即便最终我完成了非常多的图表,但实际上我只考虑实现,不考虑性能(也暂无能力考虑),所以即便是我写出来的功能,也需要工程师把关和优化。

即便如此,我直接接触数据源并动手用 grafana 实现,也有很显著的好处:
1、我更清楚原始数据已采集了哪些,哪些指标是我可以定义和统计的,哪些是需要工程师进一步支持的。
2、一些相对简单的、对业务有帮助的数据监控/统计,我能直接实现。无需 整理描述需求-和工程师沟通-工程师理解后实现-我再验收这样复杂的过程。
3、作为需求的发起者,我那些不成熟的需求,自己动手过程中迭代起来也会非常效率。

当然这些想法是需要和工程师、上级沟通清楚的,这样才不至于产生误解吖。如果我的笔记对你有帮助,那就点赞或留言告诉我吧!

【笔记】代码在24H干活,如何监控代码的执行情况?

编程新手和 print() 的关系,简直一言难尽。

第一句hello world 要用print() 写。当入门后,写了一些持续执行的脚本,需要监控运行状况时,也需要用 print()来打印日志。

后来我开始动用操作系统自带的计划任务来自动执行一些脚本时,连终端打印也没办法即时看了,那么就写文件吧。

我用的是file.open() 来写 .txt 文件。

大佬“QS”指导说,可以用 logging 模块。emm?这是个新鲜东西。我且研究下。

http://www.cnblogs.com/dahu-daqing/p/7040764.html

这篇文章好详细。。python logging模块

【代码】用 python 写个小爬虫监控某人的 CSDN 文章数据

python / pandas + mysql 写了一个简单的小爬虫,用来爬取 我的 csdn 文章基本数据。python代码如下。如果不用 mysql,把文件读写的部分改成 pandasread_csv / to_csv 也OK。

如果想监控某大佬,或某一组 csdn id 的数据,也可以这么干。不过需要在此基础上简单加工下。

如果想要持续采集数据,定时执行,可以用到操作系统自带的计划任务功能。

当数据量积累起来后,可以根据数据爬取与分析的目的,用 pandas 进一步统计分析。

import datetime
import re
import urllib.request
import pandas as pd
import random
import pymysql
import os.path

from sqlalchemy import create_engine
conn = create_engine('mysql+pymysql://root:password@localhost:3306/zhihuclawer',encoding='utf8')  

csdn_path = 'D:/crawler/output_csdn/'
wf_log = open(csdn_path + 'log_csdn_my_article.txt', 'at')

# 读取网页,把读取的数据返回为一个移除了换行空格等符号的 str 对象,供后续 re 处理调用
def read_url(url):
    #header库实现随机header,一定程度上克制反爬
    headers_list = [
        ("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.112 Safari/537.38"),
    ]
    rand = random.randint(1,len(headers_list))
    opener = urllib.request.build_opener()
    opener.addheaders = headers_list.copy()[rand-1:rand]
    data = opener.open(url).read()
    html_text = str(data,encoding='utf-8')
    html_text = clean_str(html_text)
    return html_text

def clean_str(str_obj):
    str_obj = str_obj.replace('\n','')
    str_obj = str_obj.replace('\t','')
    str_obj = str_obj.replace(' ','')
    str_obj = str_obj.replace(' ','')
    str_obj = str_obj.replace('\r','')
    return str_obj

def read_a_page(url):
    html_text = read_url(url)
    attn = r'<h4class=""><ahref="(.*?)"target="_blank"><spanclass="article-typetype-(.*?)float-none">(.*?)</span>(.*?)</a></h4><pclass="content"><ahref="(.*?)"target="_blank">(.*?)</a></p><divclass="info-boxd-flexalign-content-center"><p><spanclass="date">(.*?)</span></p><pclass="point"></p><p><spanclass="read-num">阅读数<spanclass="num">(.*?)</span></span></p><pclass="point"></p><p><spanclass="read-num">评论数<spanclass="num">(.*?)</span></span></p></div></div>'
    result = re.findall(attn,html_text,re.S)
    if result:
        article_df = pd.DataFrame(result,columns=['articlt_url','articlt_itype','articlt_type','articlt_title','articlt_url_2','articlt_desct','press_time','read_count','reply_count'])
        article_df['update_time'] = str(datetime.datetime.now())
        pd.io.sql.to_sql(article_df, "csdn_my_article", conn, if_exists='append', index=False)
        print(datetime.datetime.now(),url,'is done.')
        wf_log.write(str(datetime.datetime.now()) + str(url) + 'is done.\n')
    return article_df

def read_all_pages(pages=5,csdn_id='qiaoanlu'):
    print(datetime.datetime.now(),'read_all_pages ...')
    wf_log.write(str(datetime.datetime.now()) + 'read_all_pages ... args:' + str(pages) + ', ' + csdn_id+'\n')
    for i in range(1,pages+1):
        url = 'https://blog.csdn.net/' + csdn_id + '/article/list/' + str(i) + '?'
        try:
            read_a_page(url)
        except:
            print(datetime.datetime.now(),'some error happended',i)
            wf_log.write(str(datetime.datetime.now()) + str(i) +'some error happended')
            continue
    print(datetime.datetime.now(),'read_all_pages is done.')
    wf_log.write(str(datetime.datetime.now()) +'read_all_pages is done.\n')

def output_file():
    conn = pymysql.connect('localhost','root','789351','zhihuclawer')
    cursor = conn.cursor()
    sql_search = 'select * from csdn_my_article;'
    csdn_my_article = pd.read_sql(sql_search,conn)
    cursor.close()
    conn.close()

    rlt_url = csdn_path + 'csdn_my_article'+str(datetime.datetime.now())[:10]+'.csv'
    csdn_my_article.to_csv(rlt_url, encoding='utf_8_sig', index=False)

    print('文件已生成',rlt_url)
    wf_log.write(str(datetime.datetime.now()) + ' output_file is done.' + '\n')
    return csdn_my_article

def main():
    read_all_pages(pages=5,csdn_id='qiaoanlu')
    output_file()

if __name__ == "__main__":
    main()

如果大神路过,不妨指教下这个小爬虫脚本还有哪些可以改进的地方。感激不尽。

【实战笔记】python 时间日期之类的常用方法与类型转换(含pandas)

我自学 python 编程并付诸实战,也有三个月了吧。 pandas它可能是我最高频使用的库,基于它的易学、实用,我也非常建议朋友们去尝试学习和掌握。——尤其你本身不是程序员,但多少跟表格或数据打点交道。

pandas 善于处理 表格类数据,而我所接触的数据又天然带有时间属性,比如用户行为日志、爬虫爬取的内容文本等。于是,使用 pandas 也就意味着相当频繁地与时间数据打交道。这篇笔记将从我的实战经验出发,整理时间数据的知识技能。

与此相关的三个库是:

import time
import datetime
import pandas as pd

其中,timedatetime都是 python 自带的,pandas则是一个第三方库。换言之,前二者无需额外安装,而第三方库则需要通过pip install pandas命令行来完成安装。如果检查自己是否安装了某个库,以及如何安装、如何更新版本,则是一个对新手来说还比较大的话题,我回头另外整理一篇笔记。就不在这里占篇幅了。当然,如果你不想本地折腾安装,也可到https://xue.cn 这个网站在线写代码。

一、time模块

我的实战中,对time模块最常用到的功能就三个:

  • 指定程序休眠;
  • 获取当前时间戳;
  • 时间戳与本地时间的互相转换

time.sleep(s) 指定程序休眠时间

指定程序休眠时间,通常是在长时间运行的循环任务中进行。比如爬虫任务,控制读取网页的时间间隔;自循环任务的时间间隔,调用浏览器打开网页的时间间隔……用两个打印语句,可辅助观察和理解time.sleep()的效果:

print(datetime.datetime.now())
time.sleep(5)
print(datetime.datetime.now())

time.time()获取当前时间戳

按理说,新手阶段根本用不到时间戳技能点。但实战中,我的爬虫爬取到的仅是时间戳类型的数据,为了易读,我必须要把它转换为正常人能看懂的时间表达。同时使用 mysql 的过程中不由自主地关注起存储所占用的空间以及读写效率,我由此意识到,把时间类数据存成 char 远不如时间戳节省空间。

那么,先了解下如何生成时间戳。

通过time.time()得到的时间戳,是一个有着10位整数位、6位小数位的浮点数,可根据需要简单运算转换为需要的10、13、16位整数时间戳。

# 获取当前时间戳
a = time.time() # 值是 1569642653.1041737 ,float
b = int(a) # 1569642653,得到 10位时间戳,int
c = int(a * 1000) # 1569642653104,得到 13位时间戳,int
d = int(a * 1000000) # 1569642653104173,得到 16位时间戳,int

接下来,了解一下时间戳和人类易读的时间之间的转换。

时间戳与人类易读的时间互相转换

如上面所示,时间戳是一个float或int类型的数值,至少有10位。如果超出10位,需要加工成10位整数位。

把时间戳转换为人类易读的时间,用到的是localtime(),与其相反的是mktime()能把人类易读的时间转换为时间戳。

# 时间戳转换为人类易读的时间
# 结果是:time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=12, tm_min=12, tm_sec=1, tm_wday=5, tm_yday=271, tm_isdst=0)
# 数据类型是 time.struct_time
e = time.localtime(a)
f = time.localtime(b)
g = time.localtime(c//1000)
h = time.localtime(d//1000000)

# 人类易读的时间转换为时间戳
# 结果是:1569643921.0,float
i = time.mktime(e)
j = time.mktime(f)
k = time.mktime(g)
l = time.mktime(h)

但问题是,time.struct_time 这个数据类型,对人类依然不是最友好的。最友好的表达是文本类型即string字符串。那么,这两者之间如何互换呢?这将用到 strftimestrptime 这两个方法啦。

# 把 struct_time 转换为指定格式的字符串
good = time.strftime("%Y-%m-%d %H:%M:%S %A", e) # '2019-09-28 12:12:01 Saturday'

# 把字符串转换为 struct_time
# 结果是:time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=12, tm_min=12, tm_sec=1, tm_wday=5, tm_yday=271, tm_isdst=-1)
nice = time.strptime(good,"%Y-%m-%d %H:%M:%S %A")

当然,我刚实战数月,常用、能用到的知识点并不多。如果有小伙伴希望精进,直接搜:time site:python.org 可以访问官方文档查看超多方法说明。

【笔记】pandas.to_sql()失败,遇到 pandas.io.sql.DatabaseError:1146 提示表格不存在的解决办法

在写我的爬虫脚本 csdn_my_article 时,遇到一处报错:

image

pandas.io.sql.DatabaseError: Execution failed on sql 'select * from csdn_my_article;': (1146, "Table 'zhihuclawer.csdn_my_article' doesn't exist")

相关的代码是:

pd.io.sql.to_sql(article_df, "csdn_my_article", conn, if_exists='append', index=False)

因为该爬虫脚本是首次运行,mysql 中并没有该 table,在执行上述语句时,将会自动创建新表格。但显然,创建新表格遇到问题,导致创建表格失败。

经检查,失败的原因是:

    attn = r'some_(.*?)attn_(.*?)desct_(.*?)'
    result = re.findall(attn,html_text,re.S)
    if result:
        article_df = pd.DataFrame(result,columns=['some_columns','title_list'])

我在执行该脚本之前,曾修改正则匹配式 attn里的描述,导致多抓取一个变量,但在定义 article_df 这个 pandas dataframe 数据时,忘记定义该参数的 columns 名称。从而导致正则匹配拿到的每项结果的参数个数,比 dataframe 所定义的 columns 个数要多。最终导致接下来to_sql() 执行失败。

columnslist 中增加对应的 columns ,果然能正常执行。

【笔记】vscode中pd.ExcelWriter的用法报错,而在jupyter lab中正常

今天是周一,用 python 脚本跑 xue.cn 数据统计分析的脚本,并输出结果到 excel 时,遇到一个报错:

image

代码中有以下报错:
image

Abstract class 'ExcelWriter' with abstract methods instantiatedpylint(abstract-class-instantiated)

这个报警,自从我用 ExcelWriter方法时,一直就有,之前未产生异常。不过这次却直接导致代码没能运行通过。

而在 jupyter lab中,该代码就能直接运行通过,并正确输出结果。

什么原因,尚需探究。先记录下。

【笔记】win10 设定计划任务时提示所指定的账户名称无效,如何解决?

我想把我的 python 爬虫脚本设定为自动定时执行,我的设备是win10 操作系统,这将用到系统自带的计划任务功能。且我希望不管用户是否登录都要运行该定时任务,但在设置计划任务的属性时,遇到一个报错:所指定的账户名称无效

该报错是如何发生的,以及如何解决?记录如下:

报错是如何发生的?

如下图所示,设置计划任务的属性:

  • 如果仅勾选“只在用户登录时运行”,点击“确定”后直接创建成功。并不会遇到如题报错。

  • 如果勾选“不管用户是否登录都要运行”,点击“确定”后弹出账户信息输入界面。这种情况才会遇到这个错误。

image

这种情况下,正确输入密码,也会遇到报错:所指定的账户名称无效

image

报错截图:任务 name 出错。错误消息:所指定的账户名称无效。

image

如何解决该报错?

我搜了好多办法,唯一对我的情况有效的解决办法是:在计划任务属性页面,点击“更改用户或组”,输入用户名(比如我的“75801”),然后点击“检查名称”,再点击“确定”提交,就可以了。

请留意,执行该操作前与之后,“安全选项-运行该任务时,请使用下列用户账户”那里发生了变化。

image

image

无论是设定计划任务,还是修改计划任务的属性,当勾选了“不管用户是否登录都要运行”后,都有可能遇到此类报错。都可以按照这个方式解决问题。

【问题】把pandas中的时间戳改成 常规日期时间

data['timestamp'] = data['OCC_TIM'].apply(lambda x:time.mktime(time.strptime(x,'%Y-%m-%d %H:%M:%S')))

这个方法未成功,
报错:
ValueError: time data '1568686633' does not match format '%Y/%m/%d %H:%M:%S'


ValueError Traceback (most recent call last)
in
1 import time
----> 2 base_info['last_activity'] = base_info['lase_active_time'].apply(lambda x:time.mktime(time.strptime(str(int(x)//1000),'%Y/%m/%d %H:%M:%S')))

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\series.py in apply(self, func, convert_dtype, args, **kwds)
4036 else:
4037 values = self.astype(object).values
-> 4038 mapped = lib.map_infer(values, f, convert=convert_dtype)
4039
4040 if len(mapped) and isinstance(mapped[0], Series):

pandas_libs\lib.pyx in pandas._libs.lib.map_infer()

in (x)
1 import time
----> 2 base_info['last_activity'] = base_info['lase_active_time'].apply(lambda x:time.mktime(time.strptime(str(int(x)//1000),'%Y/%m/%d %H:%M:%S')))

C:\ProgramData\Anaconda3\lib_strptime.py in _strptime_time(data_string, format)
569 """Return a time struct based on the input string and the
570 format string."""
--> 571 tt = _strptime(data_string, format)[0]
572 return time.struct_time(tt[:time._STRUCT_TM_ITEMS])
573

C:\ProgramData\Anaconda3\lib_strptime.py in _strptime(data_string, format)
357 if not found:
358 raise ValueError("time data %r does not match format %r" %
--> 359 (data_string, format))
360 if len(data_string) != found.end():
361 raise ValueError("unconverted data remains: %s" %

另外一个方法成功:

base_info['last_activity'] = [time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(int(x)//1000)) for x in base_info['lase_active_time'].values]

如何用python做数据统计与分析?

有以下几个方法:
1、获取数据接口API,自己写python脚本,统计并输出结果为excel文件。
我已经打通这个流程,并能输出了。
写好的脚本,目前也能重复用一段时间。

2、更高阶的玩法,是pandas。
被人推荐,网上搜也发现很多人推荐。于是打算研究下。

3、一个神奇的开源工具
相关文章:
再见Excel!我开源了一款与Python深度集成的神器级IDE
https://mp.weixin.qq.com/s/fLwbYu18mCGmG_zvIgqU2g
看上去很神奇。

不过2 和3如何取舍呢,先学哪个?

【笔记】mysql 数据分析如何实现日报、周报、月报和年报?

以天为统计周期,是常见需求。周报、月报更是常见需求。长周期项目,甚至有年报需求。我已经掌握了mysql中按天统计,如何实现按年、按月、按周统计呢?

1、已掌握的技能:按天统计

实现以天为统计周期很简单。具体来说,date() 函数可返回时间数据的日期,即仅有年月日,没有时分秒信息。结合 group by 可实现按天统计。

以天为统计周期的数据指标非常多,随便举例,比如每日新增注册用户数。

select
    date(created_at) as 注册日期,
    count(user_id) as 用户数
from
     users
group by
    注册日期
order by
    注册日期

image

2、从已知推理,拓展技能

既然date()函数可用,那么是否有对应的 yearmonthweek 等函数可用呢?这纯属我的推理,那试试看吧。

image

果然可行。但美中不足的是,返回的周数和月数不带年份。当数据量跨年时,它会把每年相同周数或月数的数据加在一起。如何实现某年某月某年某周呢?已有知识储备去推理,没找到答案,那就直接搜索吧!

3、搜索找答案

经过搜索和尝试发现,在mysql中用date_format(column_name,'%Y-%m')来代替month()就能拿到年月值。

image

如果把其中代表月month的关键字m换成周week呢?试试看。分别尝试:
date_format(column_name,'%Y-%w')date_format(column_name,'%Y-%W')
image

数据返回结果不对呀?并不是预期的今年第几周。小写的w返回的是本周第几天,大写的W返回的是周几的英文名。如何拿到今年第几周这个值,实现周报的统计周期呢?

4、觉察知识点欠缺,查漏补缺

我自学编程时,很喜欢从已知去推理,拓展自己的技能。通常推理能带来惊喜,当推理不够用时,那就搜索大法好。搜索特定问题的答案时,通常也能发现某块知识不足。比如我这里我就意识到自己不熟悉表达日期的关键字或常用语法。

恰好搜索时遇到相濡以沫66的文章,里面有很好的整理。

MySQL日期格式化(format)取值范围。

  含义
%S、%s 两位数字形式的秒( 00,01, ..., 59)
%I、%i 两位数字形式的分( 00,01, ..., 59)
小时 %H 24小时制,两位数形式小时(00,01, ...,23)
%h 12小时制,两位数形式小时(00,01, ...,12)
%k 24小时制,数形式小时(0,1, ...,23)
%l 12小时制,数形式小时(0,1, ...,12)
%T 24小时制,时间形式(HH:mm:ss)
%r 12小时制,时间形式(hh:mm:ss AM 或 PM)
%p AM上午或PM下午
%W 一周中每一天的名称(Sunday,Monday, ...,Saturday)
%a 一周中每一天名称的缩写(Sun,Mon, ...,Sat)
%w 以数字形式标识周(0=Sunday,1=Monday, ...,6=Saturday)
%U 数字表示周数,星期天为周中第一天
%u 数字表示周数,星期一为周中第一天
%d 两位数字表示月中天数(01,02, ...,31)
%e 数字表示月中天数(1,2, ...,31)
%D 英文后缀表示月中天数(1st,2nd,3rd ...)
%j 以三位数字表示年中天数(001,002, ...,366)
%M 英文月名(January,February, ...,December)
%b 英文缩写月名(Jan,Feb, ...,Dec)
%m 两位数字表示月份(01,02, ...,12)
%c 数字表示月份(1,2, ...,12)
%Y 四位数字表示的年份(2015,2016...)
%y 两位数字表示的年份(15,16...)
文字输出 %文字 直接输出文字内容

把单个知识点,稍微提升到某块知识点,能让自己的知识技能再上一个台阶。

5、求助也是社交,问人附红包

上述表格相当实用,但依然没有解决如何获得“某年第几周”的需求。

虽然说主动检索找到答案,是很好的习惯。但自己耗费大量时间也没找到答案,又恰恰有目标相同的人一起互助,何不问问人看呢?学习么,本质上是个社交行为。在学一样技能时,我喜欢泡几个氛围好的学习群。经常在群里分享自己的心得笔记,也会主动力所能及地帮助别人,或者提出自己的疑问引发探讨。求助就是一种很好的社交行为啊。

此时我把疑问丢到编程学习群,并附上红包请教。经指点很快得到答案,用到了concat()函数来拼接。

image

方便大家拷贝学习,放一下代码吧:

select
    concat(date_format(created_at,'%Y-'),week(created_at)) as 年周,
    count(user_id) as 用户数
from
     users
group by
    年周
order by
    年周

6、小结

总结一下,mysql中可通过date_format()concat()week()等函数可完成数据分析中常用的月报、周报中按月、周统计的需求。关键语句为:

  • date(column_name) as 年月日
  • date_format(column_name,'%Y-%m') as 年月
  • concat(date_format(column_name,'%Y-'),week(column_name) as 年周

这篇笔记除了知识点,我也放了自己探索扩展技能的思路。是否对你有启发呢?如果有,记得留言或点赞告诉我,鼓励我多多分享。

特别申明:这篇笔记中图中数据为本地数据库,仅供本人练习使用,并非任何产品网站的正式数据。

【笔记】告别硬编码,mysql 如何实现按某字段的不同取值进行统计

上周我突然意识到,我在grafana上写的 sql 语句存在多处硬编码。这篇笔记将记录如何实现没有硬编码的sql语句,以及自学编程过程中如何应对自己的笨拙代码和难题不断的状况。

1、有效但粗笨的硬编码

所谓硬编码,大意是指代码中出现很多具体的取值,每个取值都是手动赋值的。比如:

-- 达成某个成就的用户数
select
    count(user_id) as 用户数
from 
    achivement_table
where
    achivement_name= '牛刀小试'

以我家产品 xue.cn 的成就系统为例,我们首个版本仅有10个成就,我要拷贝粘贴修改成就名称达10次。最近成就升级到V2版本,有17个成就,未来还会有更多成就。再比如习题和章节,每本书的章节数和习题数,都是几十个起。至于统计每本书的阅读用户数,每个章节的留言数,每个成就的达成用户数……这类实现太频繁了。

如果全部采用硬编码,我意识到这将低效粗笨。

在初学编程时,你我总会写出一些低效但生效的代码。随着编程水平提升或需求变得复杂,我们将有机会迭代自己的代码。迭代是好事,但这不意味着之前的低效但有效的代码是坏事。——**接纳自己早期的笨拙,并追求持续的进步。咱们不需要为自己初学阶段的代码感到不好意思或羞愧,而是要视之为提升的机会。**这个心态令我在自学编程的路上几乎无所畏惧。

2、知道,但用时忘

如何实现代码自动获取每个取值,并按该值分别统计呢?我搜索到一些代码,却看不懂:

image

不得已,我准备好问题描述,并发红包在编程学习群里请教。群友给出的答案让我哭笑不得:

特么这方法我不是会吗!?鬼打墙啦。

这种现象在初学技能时,是不是挺常见的!?知道,但不熟练。知道知识点,但实战时可能想不起来。或者知道某一种实战情境,换到其它实战情境就忘了……嗯,本质上还是重复的不够,熟练度不行啊。

image

既然是我已知的知识点,立即实操吧。

情境A:字段取值范围在同一表格

想要统计的原数据,和该字段的所有取值范围,在同一张数据表时,代码简单如下。

-- 所有成就的完成用户数
select
    achivement_name as 成就名称,
    count(user_id) as 用户数
from 
    achivement_table
group by
    成就名称
order by
    成就名称

情境B:字段取值范围在另一表格

想要统计的原数据,和该字段的所有取值范围,不在同一张数据表时,代码仅稍微复杂一点点。

-- 所有成就的完成用户数
select
    achivements.name as 成就名称,
    count(achivement_event.user_id) as 用户数
from 
    achivement_event,achivements
where
    achivement_event.name = achivements.name
group by
    成就名称
order by
    成就名称

3、解决一个难题,新的困惑到来

硬编码的问题现在倒是解决了,但实现数据可视化时,又有新的情况产生。

之前的硬编码风格,在 grafana 上通过 add query 完成,该操作是新增数据列,使得数据结果是一行多列,每个成就名就是一列。

image

image

这种数据,用 grafana 的 bar gauge 图表类型展示效果很不错。

image

之后没有硬编码的sql语句,得到的数据结果是多行2列,首列是成就名,次列是用户数。相当于之前数据结果的倒置。

行列倒置在 python pandas中,就是对dataframe数据一个T操作而已。但在 grafana 上如何灵活地操作行列,我还有不少困惑要解决。——这并非我的不足,这是我将要提升的机会,对不?

小结

在这篇笔记中,我不仅记录了自己如何完成按某个字段的取值范围进行统计的需求,既有早期的硬编码风格,也有升级版的语句。其中我还分享了自己如何看待初学编程时的笨拙代码,如何应对一个难题接着一个难题的编程自学过程。

希望我的笔记,带给你启发和力量。

【笔记】python文件、log文件和输出表格文件都越来越多,怎么办?

python 类文件:

逻辑有调用,放在一个目录下。比如 数据统计,与 爬虫 分开的。爬虫则有独立文件夹。

业务逻辑,根据对象放在一个文件中。比如zhihu相关的业务逻辑,都在zhihu_base.py 中写好。
具体的持续执行调用,则另外写小脚本调用即可,然后用计划任务执行该脚本。

比如知乎的业务逻辑可能分好多个。

日志文件、输出文件、输入文件,则统一放在一个文件夹里,并和爬虫、数据统计平级。
主要是方便查看。每次切换文件夹是很麻烦的事情。

【代码】重复执行某个任务,并实现一定程度的控制次数和随机

我在实战中经常遇到一个情况,即在很长的一段时间内,比如数日、数月地重复执行某个脚本,并非连续执行,每次执行有时间间隔。摸索实践下来,共有 3 种解决方案:

  1. 利用操作系统自带的“计划任务”
  2. 写一个自己调用自己的函数
  3. 利用第三方库:apscheduler

如何设定操作系统自带的“计划任务”,我已经写了一篇笔记:《windows 10 如何设定计划任务自动执行 python 脚本?》

该方式的好处是,自己不在电脑前,也可设定电脑自动开机执行指定任务。尤其是持续数月的某些脚本,譬如,我会每天抓取一次自己在csdn的文章浏览量数据,或每天分几个时段抓取一下知乎指定话题下有哪些热门问题。

不过即便掌握了设定计划任务这个技能,依然会用到第二个方法:

import your_model as yours
import time
import random


def repeat_myself(how_many_times = 10):
    print('--------',how_many_times,'----------')
    # 被封装的核心代码
    yours.one_def() 

    # 自循环减 1 ;如果剩余次数是0,则终止自循环
    how_many_times += -1
    if how_many_times == 0:
        print(datetime.datetime.now(),'stop it.')
        return

    # 每次调用设定一个时间间隔
    print(datetime.datetime.now(),'have a rest')
    how_long = random.randint(30,120)
    time.sleep(how_long)
    return repeat_myself(how_many_times)

# 该参数可视具体业务需要,自己设定。
repeat_myself(12)

先把核心的业务写在一个 your_model .py 文件里,然后新建一个this_sample.py文件来调用该业务。在设定计划任务时,直接把this_sample.py设为执行对象即可。这将让执行的频率、周期控制更加灵活。

如果是短期内重复,比如 48 H 内多次间隔执行,那么直接用上述自重复代码而不必用到计划任务了。

其实以上说辞,均无需记忆。当你有这个间歇重复执行的脚本时,知道有以上几种方式然后再具体掌握即可,现在只需知道有这样的线索。

【笔记】数据分析师如何自力更生统计用户行为频次?

不懂数据分析的 growth hacker 不是好运营。近日我想要统计我家产品 xue.cn 用户的编程自学行为的频次,且在不给技术开发部门带来任何新需求的情况下自力更生。那么,我该如何定义并统计这个数据指标呢?

1、定义学习这个行为。

某些行为是单个事件,某些行为是多种事件的组合。

xue.cn 用户的编程自学行为包括:完成某书一个章节的阅读、完成一道习题、获得一个成就、提交一次评论,完成一次心得打卡等,未来还会有更多。不过,虽然我们有聊天室,但因为使用的是 gitter ,所以数据采集并不容易,这个行为就暂忽略。

以上编程自学行为事件数据分布在产品数据库的多个表中。

2、日志数据的初步筛选。

通过在多个表中联合查询 user_id,事件发生日期得到每个 user_id 有学习行为的日期数据,我的 sql 语句是这么写的:

with data_study as( -- 获取有学习行为的用户名单及学习事件发生时间
    select 
        date(created_at) as time,
        user_id
    from user_comment
    union all
    select 
        date(created_at) as time,
        user_id
    from user_activity
    union all
    select 
        date(created_at) as time,
        user_id
    from study_card
)
select -- 获取学习用户的学习日期数据
    user_id,
    min(time) -- 某天有多次学习行为,仅取一条即可
from data_study
group by user_id,time
order by user_id

3、统计的基准线

游客体验功能是近期刚上线的。已有的学习行为数据,属于较早版本,那时用户产生学习行为的前提是至少完成一次时长兑换或小额RMB充值,所以本次我以用户首次付费的日期作为统计的基准线。

从日志数据筛选获取用户的首次付费日期数据,我的 sql 语句是这么写的:

with data as( -- 获取用户付费日期
    select 
        user_id,
        used_at as 付费日期
    from 
        free_coupons 
    where 
        user_id is not null 
    union all
    select 
        user_id,
        created_at as 付费日期
    from 
        rmb_order
    where order_status = 'PAY_SUCCESS'
)
select  -- 筛选付费用户的首次付费日期
    user_id,
    date(min(付费日期)) as reg_date
from
    data
group by 
    user_id

4、统计与分析

至此,有用的数据已从日志中初步筛选统计得到。接下来,用学习日期 - 首次付费日期得到血虚行为发生于首次付费后的第N天。其后统计:

  • A:首次付费后的第N天仍有学习行为的用户数。
  • B:首次付费后的第N周(取值0至8),学习天数达到M天(取值1至7)的的用户数。

A可作为付费版留存率数据。B则是学习频次分布数据。

因为我对复杂的 sql 运算还不熟练,所以实操时把第 2 和 3 步的结果从 grafana导出为 csv 文件,然后采用excel,部分指标则采用 python pandas完成演算。

5、精细选择用户群体

虽然当前 xue.cn 功能已经完善很多,其实我们是上半年刚立项,这半年多持续开发,某些学习功能在早期并未提供。于是,为了获取更可信、有效的数据,需要剔除早期批次的用户。

具体来说,根据用户首次付费日期,按月拆分用户批次,再拆分统计学习行为数据较为完善的近期批次数据。

6、小结

以上就是我完成 xue.cn 用户学习频次指标的指定与统计分析的实操过程。这次数据洞察探索,帮我发现好几处增长线索。

笔记的第4、5步对于运营、市场人员都是常用操作,我就不详细贴步骤或演算方式啦。而前面的第2、3步,我是通过 grafana 直接用查询语句与我们家产品的数据库交互。之前我写过一篇 grafana 的上手笔记,它还是相当简易的。——具体到我的本次需求来说,是否采用 grafana 不关键,grafana 只是一种工具,关键是要能与产品数据库交互拿到原始数据。

笔记虽然解决的是编程自学行为,是我家产品为用户所提供价值的核心表现,但思路也可借鉴用于其它产品、其它行为频次的统计。如果对你有帮助或启发,那就点赞或留言告诉我,鼓励我分享更多笔记吧!

【笔记】python 字符串替换功能 string.replace()可以用正则表达式,更优雅

说起来不怕人笑话,我今天才发现,python 中的字符串替换操作,也就是 string.replace() 是可以用正则表达式的。

之前,我的代码写法如下,粗笨:

image

自从发现了正则表达式也生效后,代码变得优雅简洁:

image

备注:上图中的base_infopandas 里的 dataframe 数据结构,可以用上述方法使用 stringreplace 方法。

【笔记】如何得知自己的计划任务正常运行?

我部署了一组计划任务,在过去几天任其运行。今天需检查下,这些计划任务是否正常执行。

btw,即便我电脑关机,这些计划任务也会自动启动电脑。

1、检查计划任务的执行记录

image

2、检查输出类(比如把结果写入文档)的文档记录

没有产生文件!!error

3、是不是脚本导产生N个数据库连接,导致运行失败?

检查数据库连接,至少当前正常的

image

4、是不是文件路径不对

直接本地搜文件名,未发现文件,error

文件确实未生成

5、检查 log

代码中有log记录相关的代码:

image

查看日志文件,最后一次更新是假期之前。。

6、直接运行脚本文件(设定为计划任务附加参数A的那个文件),排除代码问题

一个脚本可正常运行,检查输出结果正常

image

另一个脚本运行后,则一直无反应

添加更多 print 来查找错误,定位追踪错误(之前用了太多try...except 来提高健壮性的结果就是,真的出错时,需要一点点追溯定位。。而没有抛出错误)

image

image

emmm 找到大概那块代码有问题了,创建环境到 jupyter lab 中调试。

【笔记】打开一个文件,或连接一个数据库,何时关闭呢?

举个例子。

与知乎爬虫相关的业务逻辑,我放在一个 python 文件中 zhihu_base.py

在这个文件中,我有2个处理,
一个是连接数据库,方便多个函数调用,并读写数据库;
一个是打开一个文件对象,自定义日志记录。

我另外写了多个小的python脚本,直接调用上述 zhihu_base.py 中的函数,设定为操作系统的定时任务来自动执行。

比如:
监控指定话题的热门问题,抓取问题id,每天多次,每隔1~3小时进行一次。
根据上述问题id,抓取问题详情,比如标题,描述,阅读量,关注人数等。每天一次即可。然后顺便把已有问题详情输出一份excel文档。
比如,监控指定大V的关键数据变化。每隔几天一次。
你瞧,共有3个脚本。以不同的频率和逻辑运行。

那么,我关心的问题是:

我在 zhihu_base.py 中所设定的 数据库连接、与文件打开 ,其后的close怎么办?

目前还不知道答案。也尚未发现异常。只是直觉此为不妥。

观察一下。

【需求】如何给用户分组

共有3种激活途径,根据激活的先后顺序,来判断该用户属于哪个途径。

1、获取3种途径的user_id,激活时间(合并),途径id
2、group by user_id ,取最小的时间值,实现给用户分组成功

【笔记】整理我最常用的 mysql 语句

9 月初,我对 python 爬虫 燃起兴趣,但爬取到的数据多通道实时同步读写用文件并不方便,于是开始用起mysql。这篇笔记,我将整理近一个月的实战中最常用到的 mysql 语句,同时也将涉及到如何在python3中与 mysql 实现数据交换。

关于工具/库,特别说明下:

1、我安装了 mysql ,并直接采用管理员身份运行命令行提示符(cmd)查看 mysql,并没有安装任何 mysql 的可视化图形界面工具。

2、在 python 脚本中,我采用 pymysqlsqlalchemy 这两个库与 mysql 建立连接,用 pandas 来处理数据。

一、建立连接与数据交互

与 mysql 交互的方式,我目前共使用 4 种。其中采用管理员身份运行命令行提示符(cmd)查看 mysql,其操作图示可另写一篇。这里就不占篇幅了。mysql的可视化图形界面工具,我目前并没有用到,也没有迫切使用它的需要。另外 3 种方式都是通过 python 脚本进行。

情境A:python 演算得出数据,想要写入数据库

python 脚本已得到表格类大量数据,想要一次性写入数据库,常用代码如下:

import pandas as pd
# 与 mysql 建立连接
from sqlalchemy import create_engine
conn_eng = create_engine('mysql+pymysql://username:password@localhost:3306/databasename',encoding='utf8')  

# 调用 pandas 的方法,数据写入mysql
pd.io.sql.to_sql(your_df, "table_name", conn_eng, if_exists='append',index=False)

表格类数据,我用的是 pandasdataframe 结构。pd.io.sql.to_sql() 的参数还有许多其它用途,但上面这种是我个人使用最高频的。效果是:无需自己提前建表,将自动建新表。美中不足是:表的列属性自动生成,通常不合心意,还需检查和修改。

如果不想用 pd.io.sql.to_sql() 或者想更精细、复杂的操作,则用到下面的情境C。

情境B:python 脚本想从 mysql 拿到数据

如果已经存在某个表格,想要向该表格提交某条指令,需返回数据,我用的是 pandasread_sql () ,返回的数据类型是 pandasdataframe。sql 查询语句挺好写的,具体总结在本文下方。

import pymysql
# 与 mysql 建立连接
conn = pymysql.connect('localhost','username','password','databasename')
# sql 语句定义为一个字符串
sql_search = 'select question_id from topic_monitor where is_title=0 ;'
# 调用 pandas 的 read_sql() 方法拿到 dataframe 结构的数据
question_ids = pd.read_sql(sql_search,conn)
# 关闭连接
conn.close()

情境C:python 脚本单方面向 mysql 发出指令,无需拿到数据

如果已经存在某个表格,想要向该表格提交某条指令而无需返回数据时,比如:建表、对数据的增改删、对列的名称、列的属性修改等,代码如下。

import pymysql
# 与 mysql 建立连接
conn = pymysql.connect('localhost','username','password','databasename')
cursor = conn.cursor()
# sql 语句定义为一个字符串,插入一行数据
sql_insert = 'INSERT INTO questions(q_id,q_title,q_description,q_keywords,q_people,q_pageview,time) VALUES( "'\
                + str(quesition_id) + '", "' + str(one[0])+ '", "' + str(one[1]) + '", "' + str(one[2]) + '", "' \
                + str(one[3]) + '", "' + str(one[4]) + '", "' + str(datetime.datetime.now()) + '");' 
# sql 语句定义为一个字符串,修改某个数据(另一个表格)
sql_update = 'update topic_monitor SET is_title="1" where question_id = "' + str(quesition_id) + '";'
# 提交指令
cursor.execute(sql_insert)
cursor.execute(sql_update)
conn.commit()

# 插入一行数据;仅当该数据与表格已有数据不重复时才插入,否则就不会插入
sql_insert = 'INSERT INTO `topic_monitor`(question_id,is_title,q_type,topic_id,time) SELECT "'\
                    + x[0] + '", "0", "0","'  + str(topic_id) + '", "'+ str(now) + '" FROM DUAL WHERE NOT EXISTS(\
                    SELECT question_id FROM topic_monitor WHERE question_id = "' + x[0] + '")'
cursor.execute(sql_insert)
conn.commit()

# 关闭连接
cursor.close()
conn.close()

通过上面几种实用情况可以看到,pythonmysql 实现交互的过程,通常分为:建立连接、把sql语句定义为字符串,提交指令、关闭连接。核心的技能在于 sql语句;除了定义sql语句字符串,其余3个处理都是固定的写法。

我在最初一个月的实践中,最常出现的错误有:

  • 值的引用没有加上引号;
  • 符号错乱:多一个符号,少一个符号;
  • 值的类型不符合:不管 mysql 表格中该值是数,还是文本,在定义 sql 语句的字符串时,对每个值都需要转化为字符串;
  • 拷贝自己的代码时,忘记修改databasename。

二、sql语句:搜索查询

搜索是指在数据库的某个表格中查询符合特定条件的数据,并返回查询结果。其基本结构为:

SELECT 【范围】FROM table_name 【条件】; 其中,范围是必须指定的,而条件可有可无。

变量A:范围,是指返回查询结果的范围。

返回该表格的所有字段,用 * 表达:

SELECT * FROM table_name ;

image

仅返回该表格的某个字段:

SELECT column_name FROM table_name ;

仅返回该表格的多个字段:

SELECT column_name_1,column_name_3,column_name_3 FROM table_name ;

image

仅返回符合条件的数据个数:

SELECT count(*) FROM table_name ;

image

变量B:条件是指,期望返回的数据满足哪些条件。

不限定条件:

SELECT * FROM table_name ;

数值类:某个字段(数值类型的,比如double或者int),数值比较的操作符都可以使用比如,大于>,小于<,等于 = ,大于等于 >= ,小于等于 <=

image

SELECT * FROM table_name WHERE num_column_name >= 1;

文本类:某个字段(字符串类型的,比如char,text):

SELECT * FROM table_name WHERE str_column_name like “%your_str%”;

image

也可以表达多个条件,andor等可用于表达条件之间的关系:

SELECT * FROM table_name WHERE num_column_name_1 >= 1 and  str_column_name like “%your_str%” ;

image

三、sql语句:修改表属性:

横向的一整条数据,叫做行;竖向的一整条数据,叫作列。列的名字,叫做 column,这是通用的知识点。

这段时间的实战中,我完全没有用到修改表的名称、重设index等知识点。最常用的,就是对列进行操作。每个列具备:列的名称、列的属性、列的数值。

列的名称,需要留心不使用保留词。我的技巧是,尽量用一些_来表达该数据,比如 article_titlepress_date 这种命名虽然稍长,但易读,也不会装上保留词。

列的属性包括:类型,最大长度,是否为空,默认值,是否重复,是否为索引。通常,直接通过 pandaspd.io.sql.to_sql() 一次性创建表格并保存数据时,列的默认属性并不合需求。要么提前自己定义表的结构,设置好每列属性;要么事后检查列属性,并逐列修改。所以,列的属性设定、修改是高频基础知识点。

列的数值,即除了列名称外的、该列其它值。修改某个值,也是高频操作。不过我把这个知识点放到第四部分了。

对列的名称、列的属性进行修改,主要的关键词都是 ALTER,具体又分为以下几种情况。

情境A:新增一列。关键词 ADD

在你所指定的 column_name 后面定义列的属性。

ALTER TABLE table_name ADD COLUMN column_name char(20);

情境B:修改某列的名称。关键词 CHANGE

在修改列名的同时也可以重新指定列的属性。

ALTER TABLE table_name CHANGE old_column_name new_column_name char(50);

情境C:修改某列的属性。关键词是 MODIFY

ALTER TABLE table_name MODIFY column_name char(100);

【done】如何给python安装第三方模块?

1、具体要安装什么模块,就去搜如何安装该模块,附带自己的操作系统:比如,win64如何安装pandas

2、基本上都是命令行运行 pip install 命令。

3、有时会遇到报错,拷贝报错信息去搜索解决方案即可。

4、如果不知道什么第三方库更好,不知道名称,那就按功能去搜有哪些好用的、流行的库。

学习过程的补充建议

《A系列:准备vscode+ github,并熟悉git的最少必要操作。》

按照本文的操作提示进行了实践学习,能否在“第3次:vscode 克隆了 github 的仓库。”的第一步git clone前,提醒Windows用户,### 首先安装git 。谢谢!

【笔记】windows 10 如何设定计划任务自动执行 python 脚本?

我用 python 写了一些脚本,有一些是爬虫脚本,比如爬取知乎特定话题的热门问题,有一些是定期的统计分析脚本,输出统计结果到文档中。之前我都是手动执行这些脚本,现在我希望如何这些脚本能自动定时执行。那么,windows 10 操作系统如何定时自动执行 python 脚本?

我的设备是 windows 10操作系统,自带的“计划任务”可以满足我的需求,具体操作步骤,整理如下。

步骤1:打开 “计算机管理” 界面

点击电脑左下角的windows图标,或者键盘的windows按键。

image

在弹出的界面中,鼠标移到“此电脑”上右键点击,选择“更多”-‘管理’,点击则可进入“计算机管理”界面。

image

步骤2:开始 “创建基本任务”

在打开的“计算机管理”界面上,依次点击“系统管理”-“任务计划程序”,然后最右侧选择“创建基本任务”,即可开始创建计划任务。

image

步骤3:输入计划任务的基本属性

计划任务的属性设置分为多个步骤,按照操作提示一步步来即可。即便刚开始弄错了,之后也可以修改或完善。所以不要紧张。第一次使用时,可按照以下截图依次尝试:

- 输入该任务的名称和描述。

注意:这是写给自己看的哟,最好标记清楚,避免时间久了自己迷糊了。

image

- 设定计划任务的频率。

注意:根据你的具体需求来设定。比如我的知乎爬虫脚本2小时一次,而统计分析脚本则每天一次即可。

对于每隔2小时一次的计划任务,也可以选择每天,后面可以增加多个时段。比如每天的6,8,10,12,14点等等分别执行。刚开始先设置一个时间点即可。之后再增加其它时间点。下文将详细说明。

对于python脚本来说,它的类型是:程序。

image

  • 程序和脚本:这里填写 python 的安装路径。点击浏览“浏览……”会自动弹出选择界面。
  • 添加参数(可选)A: 这里填写我的python 爬虫脚本的绝对路径。比如我的脚本是:

C:\Users\username\python_side_projects\crawler\crawler_base\zhihu_topic_monitor_exe.py

image

系统默认打开的路径,并没有我想打开的 python.exe 怎么办?简单……往下看。

image

这里遇到一个小知识点:

知识点:如何查找 python 安装在哪里?

启动cmd(命令行提示符),输入:where python 即可。下面看到,我的电脑上装了两个python,选择你常用的那个版本即可。

image

按照上述路径提示,打开对应文件夹,选中 python.exe 即可。

image

按照以上步骤设定好计划任务的属性,点击完成就行啦。等等……我刚才希望爬虫脚本每隔2小时就执行一次,如何设定呢?

小技巧:每隔2小时就运行一次,如何设定计划任务。

先新建一条普通的计划任务,或选择已有的计划任务,选择“属性”打开计划任务的属性界面。

image

在“触发器”这个页签,按需求,添加更多时间点,然后提交完成即可。

image

经验:遇到报错所指定的账户名称无效,怎么办?

image

简单来说,在计划任务属性页面,点击“更改用户或组”,输入用户名(比如我的“75801”),然后点击“检查名称”,再点击“确定”提交,就可以了。详细的图文说明,请挪步我的另外一篇整理:https://blog.csdn.net/qiaoanlu/article/details/100731220

这篇文章的 PRESS.one 签名:
https://press.one/file/v?s=950fee0e9bbae05fcf407c11a83a0f99dc40cc426b016be34d3298ac8c16a3673693092b79536eddfdca342c7173e766fd956e244e04d0936699a78f161bc0de00&h=94e2717c89ab8937a8dbdae8e1092e46c0c402faf4925e2281f2e261c24e2dd9&a=ed73e900e209def08ff03a2e3fadbac99af087c0&f=P1&v=3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.