Skip to content
本页目录

python全栈数据工程师养成攻略

GitHub - Honlan/fullstack-data-engineer: 全栈数据工程师养成攻略

本教程是以该仓库与同名书籍的笔记

01.写在前面的话

数据处理 或者 爬虫的流程

  1. 获取数据
  2. 存储
  3. 分析
  4. 可视化

数据结构

  • 静态数据

    这类数据不包含时间戳

    比如 地铁数据中的线路数据 首班末班车时间

  • 动态数据

    记录中带有时间

    比如 乘客的刷卡数据 包含进站出站的时间

存储的数据类型

  • txt
  • csv
  • json
  • sql

02.python的基础语法

2.1在pycharm新建一个函数main.js

python
def print_hi(name):
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.
if __name__ == '__main__':
    print_hi('PyCharm')

参考

Python3.6中的字符串格式化 – 魔力Python (opython.com)

这是一个最基本的函数 我们就以此拓展每一节的函数

2.2基本语法

python
def python02():
    # 数字
    a = 1
    b = 2.1
    print(a,b)
    # 字符串
    c = "Hello"
    d = "你好"
    print(c,d)
    print(c+d)
    print(len(c+d))
    # 位置下标从0开始
    c1 = "Hello World"
    print(c1[0],c1[-1],c[1:5],c[1:-1],c[:5],c[3:])
    # 列表 相当于数组
    arr = []
    arr.append(1)
    arr.append(2.1)
    arr.append('Hello')
    print(arr,len(arr),arr[1],arr[-1])
    arr[1] = 100
    print(arr)
    del arr[0]
    print(arr)
    # 元组
    arr2 = (1,2.1,'Hello')
    # arr2[0] = 22
    print(arr2)
    # 字典 相当于对象
    aobj = {}
    aobj['k1'] = 1
    aobj['k2'] = 2.1
    aobj['k3'] = 'Hello'
    print(aobj)
    li = [1,2,'hell']
    di = {'k1':1,'k2':2.1,'k3':'hell'}
    print(di.get('k1'))
    '''
        注释
    '''
    a2 = 1
    b2 = 2
    print(a2+b2)
    print(a2 == b2)
    c2 = True
    d2 = False
    print(c2 and d2, c2 or d2, not c2)
    a3 = 1
    # 单个条件
    if a3 == 1:
        print(1111)
    # 处理条件不成立
    if a3 == 2:
        print(222)
    else:
        print(3333)
    # 多个条件,加多少个都可以
    if a3 == 1:
        print(111)
    elif a3 == 2:
        print(2222)
    else:
        print(33333)

    # 循环
    flag = 1
    while flag < 10:
        # while一定要改变条件变量 不然死循环
        print(flag)
        flag += 1
    # x从0开始 一直9结束 即不包括后面的数字
    for x in range(0,10):
        print(x)
    # 遍历数组
    for item in li:
        print(item)
    # 遍历对象的键
    for key in di.keys():
        print(key)
    # 遍历对象的值
    for value in di.values():
        print(value)
    # 同时遍历对象的键和值
    for key,value in di.items():
        print(key,value)
    # 循环控制
    for x in range(0,10):
        if x == 5:
            pass
        else:
            print(x)
    for x in range(0,10):
        if x ==5:
            continue
        print(x)
    for x in range(0,10):
        if x == 3:
            break
        print(x)

    # 时间
    import time
    t = time.time()
    print(t,type(t))
    t1 = '2023-07-06 10:00:00'
    t2 = int(time.mktime(time.strptime(t1,"%Y-%m-%d %H:%M:%S")))
    print(t2)
    t3 = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(t))
    print(t3)
if __name__ == '__main__':
    python02()

2.3 python文件操作与异常处理

python
def python03():
    fw = open('./data.txt','w')
    for x in range(0,10):
        fw.write(str(x))
    fw.close()
    file = open('./data.txt','r')
    while True:  # 循环
        line = file.readline()  # 读取一行内容存入变量
        if line:  # 如果变量不是空值(末尾行为空值)
            print(line, end='')  # 显示输出读取结果,设置不换行输出(文本的每一行都带有换行符)。
        else:  # 否则
            break  # 结束循环
    file.close()  # 关闭文件
    try:
        print(1/0)
    except Exception as e:
        print(e)
    finally:
        print("一定会执行")
if __name__ == '__main__':
    python03()

参考

异常处理

2.4 练习:处理西游记小说的用字统计

python
def python_xyj():
    file = open('./xyj.txt','r',encoding='utf-8')
    # 出现的汉字
    characters = []
    # 每个汉字出现的次数
    stat = {}
    while True:  # 循环
        line = file.readline()  # 读取一行内容存入变量
        if line:  # 如果变量不是空值(末尾行为空值)
            # 去掉每一行两边的空白
            line = line.strip()
            if len(line) == 0:
                continue
            for x in range(0,len(line)):
                if line[x] in [' ', '\t', '\n', '', '', '(', ')', '', '', '', '', '', '', '', '', '', '','', '', '……']:
                    continue
                if not line[x] in characters:
                    characters.append(line[x])
                if not stat.get(line[x]):
                    stat[line[x]] = 0

                stat[line[x]] += 1
        else:  # 否则
            break  # 结束循环
    file.close()  # 关闭文件
if __name__ == '__main__':
    python_xyj()

结果有4491行,也就是4491个字 我们看前10行 说明是西游记中出现最多的字数

道,11078
不,8882
一,7969
了,7752
那,7516
我,7224
是,6498
来,5994
他,5751
个,5704

03.获取数据

3.1requests库的get 与 post 请求的获取

需要用到requests的请求库

书中采用的是urllib2的库 这是python2用的 python3就不适合了 就换成以urllib3开发的requests的请求库了

具体的文档:

python中requests库使用方法详解 - 知乎 (zhihu.com)

爬取目标

百度指数 (baidu.com)

稀土掘金 (juejin.cn)

python
import requests
from requests.exceptions import ReadTimeout
import json

def python_featch():
    # 掘金前端的api
    url = "https://api.juejin.cn/content_api/v1/content/article_rank?category_id=6809637767543259144&type=hot"
    response = requests.get(url)
    print(response.text)
    print(response.json())				# 使用request的内置json API
    print(json.loads(response.text))	# 使用json库的api

    # 超时设置 超过0.5s会返回Timeout
    try:
        response = requests.get("http://httpbin.org/get", timeout=0.5)
        print(response.status_code)
    except ReadTimeout:
        print('Timeout')
    # post 百度指数
    response2 = requests.post("https://index.baidu.com/Interface/homePage/pcConfig")
    print(response2.json())

3.2练习:爬取豆瓣电影

爬取目标

爬取首页 豆瓣电影 (douban.com)

查看网络请求对应的豆瓣电影的api

https://movie.douban.com/j/search_subjects?type=movie&tag=热门&page_limit=2&page_start=0

电影详情页 例如

速度与激情10 (豆瓣) (douban.com)

爬取代码

python
# 获取豆瓣电影数据并存入txt中
def python_douban():
    # 电影标签  https://movie.douban.com/j/search_tags?type=movie&source=index
    # 电影列表 https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0
    # 电影详情 https://movie.douban.com/subject/35401290/
    url_tag = 'https://movie.douban.com/j/search_tags?type=movie&source=index'
    tags = []
    # 避免返回<response 400>
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.68'
    }

    try:
        response_tag = requests.get(url_tag,headers=headers).json()
        print(response_tag['tags'])
        tags = response_tag['tags']

    except ReadTimeout:
        print('Timeout')

    # 获取电影
    movies = []
    for tag in tags:
        start = 0
        # 不断请求,直到结果返回空
        while True:
            url_movies = "https://movie.douban.com/j/search_subjects?type=movie&tag="+ tag +"&page_limit=20&page_start="+str(start)
            print(url_movies)
            try:
                response_movies = requests.get(url_movies, headers=headers).json()
                print(response_movies['subjects'])
                response_movies_data = response_movies['subjects']
                if len(response_movies_data) == 0:
                    break
                for item in response_movies_data:
                    movies.append(item)
            except ReadTimeout:
                print('Timeout')



            # 新加20
            start += 20
    print(len(movies))
    # 获取电影详情页
    python_douban_movie_detail(movies)
    #将结果写入txt中
    fw = open('douban_movies.txt','w',encoding='utf-8')
    #写入一行表头,用于说明每个字段的意义
    print("创建文件douban_movies.txt,并录入数据")

    fw.write('title^rate^url^cover^id^description\n')
    for item in movies:
        movie_info = item['title'] + '^'+item['rate'] + '^'+item['url']+'^'+item['cover']+'^'+item['id']+'^'+item.get('description')+'\n'
        fw.write(movie_info)
    fw.close()
    print("操作结束!已爬取到豆瓣电影数据")
    
# 获取豆瓣电影的电影详情页的电影介绍数据
def python_douban_movie_detail(movies):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.68'
    }
    for x in range(0, len(movies)):
        # print(movies[x])
        print("录入第",x)
        # 页面爬取数据过慢 只录取前10条
        if x == 10:
            break
        url = movies[x]['url']
        request_movie_detail = requests.get(url, headers=headers).text
        html = BeautifulSoup(request_movie_detail, "html.parser")  # 指定解析器

        try:
            detail = html.find_all("span", attrs={"property": "v:summary"})[0].get_text()
            # print(detail)
        except Exception as e:
            movies[x]['description'] = ''

        else:
            movies[x]['description'] = detail
        finally:
            pass
        time.sleep(0.5) # 0.5s请求一次 避免请求过快 无法响应
    # print(movies)

if __name__ == '__main__':
	python_douban()

获取到的数据

这里我只展示出10行电影数据

title^rate^url^cover^id^description
惊天营救2^7.5^https://movie.douban.com/subject/35056376/^https://img2.doubanio.com/view/photo/s_ratio_poster/public/p2892063382.jpg^35056376^
                                      在 Netflix 动作大片《惊天营救》的续集《惊天营救 2》中,克里斯·海姆斯沃斯将继续饰演泰勒·雷克。在第一部电影的惊险情节中侥幸逃生后,雷克又卷土重来。作为澳大利亚的黑市雇佣兵,雷克接下了又一项致命任务:从监狱中解救一个被格鲁吉亚黑帮残忍虐待的家庭。
                                        
                                      海姆斯沃斯与导演山姆·哈格雷夫再度合作,乔·罗素和安东尼·罗素的 AGBO 负责制作,乔·罗素担任编剧。格什菲·法拉哈尼将继续出演其在第一部电影中的角色,亚当·贝萨、欧嘉·柯瑞兰寇、丹尼尔·伯哈特和蒂娜婷·达拉齐施维利也将出演该片。
                                        
                                      本片是第一部电影的续集,改编自安德·帕克斯的图画小说《Ciudad》,故事由安德·帕克斯、乔·罗素和安东尼·罗素共同创作,插图由费尔南多·莱昂·冈萨雷斯绘制。《惊天营救 2》由安东尼·罗素、乔·罗素、迈克·拉罗卡、安杰拉·拉索-奥茨特、克里斯·海姆斯沃斯、帕特里克·纽...
                            
毒舌律师^7.5^https://movie.douban.com/subject/35914259/^https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2886619074.jpg^35914259^
                                  一宗国际名模涉嫌虐待女儿的冤案,竟成了法律界、权贵与名媛之间的角力场!社会金字塔顶层的钟氏家族,如何用尽权力与资源去自保?以林凉水(黄子华 饰)为代表的律师们又如何在重重困难下伸张正义?
                        
工会成员^6.5^https://movie.douban.com/subject/35321420/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2886436159.jpg^35321420^
                                  本片由伊莎贝尔·于佩尔出演,故事改编自卡罗琳·米歇尔-阿奎尔(Caroline Michel-Aguirre)撰写的同名小说,原著小说讲述2012年12月17日,在巴黎郊区的一栋房子里,一名女子被绑在椅子上,阴道内被插入一把刀柄,肚子上被刀刃划出字母“A”。她的名字叫莫林·科尔尼(Maureen Kearney),是阿海珐工会成员。
                        
两万种蜜蜂^6.9^https://movie.douban.com/subject/35519078/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2891373447.jpg^35519078^
                                  8岁露西亚生来就与众不同,她对自己要成为男孩还是女孩举棋不定。露西亚的母亲安妮正在经历自己的事业和感情危机,她带着孩子利用暑假回到与养蜂生产息息相关的母亲家中,并对小镇所有人隐瞒孩子的情况。然而露西亚认为这是她向所有人展示自己女孩形象的完美时机,哪怕人们一直以为她是男生。入围金熊奖的《两万种蜜蜂》以明亮的孩童视角探索性别的复杂多样性。
                        
怪物少女妮莫娜^7.7^https://movie.douban.com/subject/26423117/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2893914878.jpg^26423117^
                                  为了证明自己的清白,一名被诬陷犯下重罪的骑士向擅长变形的少女求助。但如果这名少女正是他曾立誓要消灭的怪物呢,他又该如何是好?
                        
MONDAYS / 如果不让上司注意到这个时间循环就无法结束^7.3^https://movie.douban.com/subject/36008597/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2876546519.jpg^36008597^
                                  一家小公司的职员们发现自己被困在办公室里永无尽头的一周循环之内,为了让关键人物部长意识到这一事实并打破循环,他们要使出浑身解数。时间循环的电影早已屡见不鲜,而能够想出“职场时间循环”这样令人惊恐又喷饭题材的,恐怕只有日本了。除了天马行空、笑料十足的精彩剧情外,本片最大亮点就是对职场及打工人真实的刻画,各种熟悉又似曾相识的桥段让无数打工人心有戚戚焉。
                        
人生路不熟^6.0^https://movie.douban.com/subject/35653205/^https://img2.doubanio.com/view/photo/s_ratio_poster/public/p2889864501.jpg^35653205^
                                  车队大佬周东海(乔杉 饰)和老婆霍梅梅(马丽 饰)阴差阳错地与女儿周微雨(张婧仪 饰)及女儿的男朋友万一帆(范丞丞 饰)同行自驾,踏上人生路不熟的探亲之旅,周东海决定借此机会给准女婿来一场全方位无死角的考察,万一帆也用生命演绎了什么叫做教科书级翻车。一路上先后遭遇周东海死对头“添堵专业户”贾主任(田雨 饰)的房车事故、微雨“青梅竹马”光子(常远 饰)的“野鸡”山庄醉酒闹剧、捉拿公路贼团“油耗子”的围堵大战,鸡飞狗跳的探亲之旅窘态百出,爆笑不断!
                        
博很恐惧^7.0^https://movie.douban.com/subject/35381711/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2886073087.jpg^35381711^
                                  男主角博是一个极度焦虑但看上去和蔼可亲的男人,因为从未见过父亲,导致他和专横的母亲关系紧张。博在一个神秘的情况下得知母亲去世,回家路上却发现关于自己的令人震惊的过去。在这旅途中,他遇到了各种疯狂的超自然威胁。
                        
我的错误^7.3^https://movie.douban.com/subject/36168684/^https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2890770708.jpg^36168684^
                                  诺亚被迫离开她的小镇、男友和朋友,搬进了她母亲的新丈夫的豪宅。在那里,她遇见了她的新继兄尼克,两人的性格从一开始就发生了碰撞。然而他们对彼此的吸引却渐渐演变成一段禁忌的恋情,在这期间,他们叛逆的性格和磨人的脾气颠覆了彼此的世界,并致使他们疯狂地坠入了爱河。
                        
小行星城^6.8^https://movie.douban.com/subject/35209746/^https://img2.doubanio.com/view/photo/s_ratio_poster/public/p2891847821.jpg^35209746^
                                  影片被描述为“对生命意义的诗意沉思”。故事发生在1955年一座虚构的美国沙漠小镇,镇上正在举办一场年轻天文学家/太空人大会,原本的计划是让来自美国全国各地的学生和家长聚集在一起进行学术竞赛并且争取奖学金,但是却意外被即将改变全世界的大事件打乱原来的行程。

遇到的问题

  1. 爬取豆瓣的数据的时候返回的结果是<Response [418]>

    1. [HTTP代码返回418<Response 418]>__pxyp123的博客-CSDN博客
    2. 爬虫只返回request <200>不返回数据_言语肤浅的博客-CSDN博客
  2. python存入数据到txt中文乱码

    1. Python小白高阶:Unicode和字节串 - 知乎 (zhihu.com)
  3. python的lambda表达式

    1. python的lambda表达式详细讲解_python lambda表达式_神的孩子都在歌唱的博客-CSDN博客
    2. [Python中的排序sorted(d.items(), key=lambda x: x1])_key=lambda x:x[1]是什么意思_Xu_lib的博客-CSDN博客
  4. python的字典读取不存在的值会报错

    1. Python3:字典(dict)读取不存在的键_python读取dict 不存在的key_风静如云的博客-CSDN博客
  5. python requests请求豆瓣接口报错

    1. HTTPSConnection 发生错误ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:841)_冲田小姐姐吃糖的博客-CSDN博客
      1. 不要开VPN