From fa43e7f5bd0a56e3e424a7ebc13ef49a7a6ee41a Mon Sep 17 00:00:00 2001
From: leeexing <674023427@qq.com>
Date: Tue, 23 Jan 2018 14:52:19 +0800
Subject: [PATCH 01/26] python I'm back. show me the code persist
---
.gitignore | 14 ++
show-me-code/code-0.py | 12 ++
show-me-code/code-00.py | 68 +++++++++
show-me-code/code-01.py | 48 ++++++
show-me-code/code-02.py | 55 +++++++
show-me-code/code-03.py | 68 +++++++++
show-me-code/code-04.py | 60 ++++++++
show-me-code/code-05.py | 140 ++++++++++++++++++
.../{README.md => show-me-the-code.md} | 2 +
9 files changed, 467 insertions(+)
create mode 100644 .gitignore
create mode 100644 show-me-code/code-0.py
create mode 100644 show-me-code/code-00.py
create mode 100644 show-me-code/code-01.py
create mode 100644 show-me-code/code-02.py
create mode 100644 show-me-code/code-03.py
create mode 100644 show-me-code/code-04.py
create mode 100644 show-me-code/code-05.py
rename show-me-code/{README.md => show-me-the-code.md} (98%)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..33a72a7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+.DS_Store
+node_modules/
+dist/
+_assets/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
\ No newline at end of file
diff --git a/show-me-code/code-0.py b/show-me-code/code-0.py
new file mode 100644
index 0000000..3643c71
--- /dev/null
+++ b/show-me-code/code-0.py
@@ -0,0 +1,12 @@
+from PIL import Image, ImageFilter
+
+def main():
+ img1 = Image.open('./_assets/images/weixin_avatar1.png')
+ # img2 = Image.open('./assets/images/weixin_avatar2.png')
+ # img = Image.blend(img1, img2, 0.5)
+ # img.show()
+ img2 = img1.filter(ImageFilter.BLUR)
+ img2.show()
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/show-me-code/code-00.py b/show-me-code/code-00.py
new file mode 100644
index 0000000..caa274e
--- /dev/null
+++ b/show-me-code/code-00.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# encoding: utf-8
+'''
+## 第 0000 题: 将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果。 类似于图中效果
+'''
+from PIL import Image, ImageFont, ImageDraw, ImageFilter
+import random
+
+def main():
+ # text = '7'
+ text = str(random.randint(0, 100))
+ img = Image.open('./_assets/images/weixin_avatar1.png')
+ img_w, img_h = img.size
+ print('Original image size:{} -- {}'.format(img_w, img_h))
+
+ # 缩放到50%. 函数内部需要是一个 元组
+ img.thumbnail((img_w // 2, img_h // 2))
+
+ dr = ImageDraw.Draw(img)
+ font = ImageFont.truetype('./_assets/ttf/simhei.ttf', 34)
+
+ dr.text((img.size[0]*0.5, img.size[1]*0.15), text, font=font, fill="#ff0000")
+
+ img.rotate(45).show()
+ # img.rotate(45).save('./dest/avarta_01.jpg', 'PNG')
+
+def rand_char():
+ return chr(random.randint(65, 90))
+
+def rand_color():
+ return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
+
+def rand_color2():
+ return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
+
+def app(n):
+ '''随机生成验证码图片'''
+ width = 60 *4
+ height = 80
+ img = Image.new('RGB', (width, height), (255, 255, 255))
+ font = ImageFont.truetype('./_assets/ttf/arialuni.ttf', 36)
+ draw = ImageDraw.Draw(img)
+ for x in range(width):
+ for y in range(height):
+ draw.point((x, y), fill = rand_color())
+ arr = []
+ for t in range(4):
+ rnd_chr = rand_char()
+ arr.append(rnd_chr)
+ draw.text((60*t + 10, 10), rnd_chr, font=font, fill=rand_color2())
+
+ image = img.filter(ImageFilter.BLUR)
+ print(arr)
+ # image.show()
+ image.save('./dist/QR-code/{}-{}.jpg'.format(''.join(arr), n), 'jpeg')
+
+def factory(num=5):
+ for i in range(num):
+ app(i)
+
+
+if __name__ == '__main__':
+ # main()
+ # app()
+ factory(50)
+
+
+
diff --git a/show-me-code/code-01.py b/show-me-code/code-01.py
new file mode 100644
index 0000000..c9749a4
--- /dev/null
+++ b/show-me-code/code-01.py
@@ -0,0 +1,48 @@
+'''
+## 第 0001 题: 做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 200 个激活码(或者优惠券)?
+'''
+import random, string
+import pymongo
+
+client = pymongo.MongoClient('localhost', 27017)
+python_QR_db = client['python']['QR_code']
+
+def main(count=100, length=20):
+ # count = 100
+ # length = 20
+ forSelect = string.ascii_letters + '0123456789'
+ qr_data = []
+ for x in range(count):
+ re = ''
+ for y in range(length):
+ re += random.choice(forSelect)
+ # print(re)
+ obj = {
+ 'type': 'discount' if x > 50 else 'activation',
+ 'qr_code': re
+ }
+ qr_data.append(obj)
+ # print(qr_data)
+ save_qr_to_db(qr_data)
+
+def save_qr_to_db(data):
+ '''将激活码保存到 mongodb 中'''
+ for item in data:
+ # python_QR_db.insert_one(item)
+ python_QR_db.save(item)
+
+if __name__ == '__main__':
+ main()
+
+
+
+
+
+# 学习
+# string.ascii_letters // 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+# random.choice从序列中获取一个随机元素
+'''
+random.choice从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。
+参数sequence表示一个有序类型。这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence
+'''
+# random.shuffle random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱
\ No newline at end of file
diff --git a/show-me-code/code-02.py b/show-me-code/code-02.py
new file mode 100644
index 0000000..8d08ec2
--- /dev/null
+++ b/show-me-code/code-02.py
@@ -0,0 +1,55 @@
+'''
+## 第 0001 题: 做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 200 个激活码(或者优惠券)?
+'''
+import random, string
+import pymongo
+
+client = pymongo.MongoClient('localhost', 27017)
+python_QR_db = client['python']['QR_code']
+
+def main(count=100, length=20):
+ # count = 100
+ # length = 20
+ forSelect = string.ascii_letters + '0123456789'
+ qr_data = []
+ for x in range(count):
+ re = ''
+ for y in range(length):
+ re += random.choice(forSelect)
+ # print(re)
+ obj = {
+ 'type': 'discount' if x > 50 else 'activation',
+ 'qr_code': re
+ }
+ qr_data.append(obj)
+ # print(qr_data)
+ save_qr_to_db(qr_data)
+
+def save_qr_to_db(data):
+ '''将激活码保存到 mongodb 中'''
+ for item in data:
+ # python_QR_db.insert_one(item)
+ python_QR_db.save(item)
+
+if __name__ == '__main__':
+ main()
+
+
+
+
+
+# 学习
+# string.ascii_letters // 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+# random.choice从序列中获取一个随机元素
+'''
+random.choice从序列中获取一个随机元素。其函数原型为:random.choice(sequence)。
+参数sequence表示一个有序类型。这里要说明 一下:sequence在python不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence
+
+random.choices 返回的是一个数组
+choices(population, weights=None, *, cum_weights=None, k=1) method of random.Random instance
+ Return a k sized list of population elements chosen with replacement.
+
+ if the relative weights or cumulative weights are not specified,
+ the selections are made with equal probability.
+'''
+# random.shuffle random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱
\ No newline at end of file
diff --git a/show-me-code/code-03.py b/show-me-code/code-03.py
new file mode 100644
index 0000000..6c91e26
--- /dev/null
+++ b/show-me-code/code-03.py
@@ -0,0 +1,68 @@
+'''
+## 第 0003 题: 将 0001 题生成的 200 个激活码(或者优惠券)保存到 Redis 非关系型数据库中。
+'''
+import redis
+import string, random
+r = redis.Redis(host='localhost', port=6379, db=0)
+
+forSelect = string.ascii_letters + '0123456789'
+def main(count=100, length=23):
+ '''生成激活码'''
+ act_list = []
+ for n in range(count):
+ activation = ''
+ for i in range(length):
+ activation += random.choice(forSelect)
+ # print(activation)
+ act_list.append(activation)
+ print(act_list)
+ save_to_redis(act_list)
+
+def save_to_redis(data):
+ for item in data:
+ r.sadd('activation:apple', item)
+
+def get_activation():
+ arr = r.smembers('activation:apple')
+ print(arr)
+
+if __name__ == '__main__':
+ main(2)
+ # get_activation()
+
+
+# redis连接实例是线程安全的,可以直接将redis连接实例设置为一个全局变量,直接使用。
+# 如果需要另一个Redis实例(or Redis数据库)时,就需要重新创建redis连接实例来获取一个新的连接。同理,python的redis没有实现select命令
+
+'''
+Redis 键命令的基本语法如下: COMMAND KEY_NAME
+
+SET runoobkey redis | DEL runoobkey
+
+1、Redis 字符串(String) :set keyName keyValue | get keyName
+
+2、Redis 哈希(Hash):HMSET keyName keyValues | HGETALL runoobkey
+ Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
+ **这个就有点像 dict 数据类型了啊**
+ eg:
+ HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
+ HGETALL runoobkey
+ 1) "name"
+ 2) "redis tutorial"
+ 3) "description"
+ 4) "redis basic commands for caching"
+ 5) "likes"
+ 6) "20"
+ 7) "visitors"
+ 8) "23000"
+
+3、Redis 列表(List) :LPUSH runoobkey redis、LPUSH runoobkey mongodb | LRANGE runoobkey 0 10
+
+4、Redis 集合(Set):SADD runoobkey redis、SADD runoobkey mongodb | SMEMBERS runoobkey // "mysql" "mongodb"
+
+5、Redis 有序集合(sorted set):ZADD runoobkey 1 redis、ZADD runoobkey 2 mongodb、ZADD runoobkey 3 mysql | ZRANGE runoobkey 0 10 WITHSCORES
+ // 1) "redis" 2) "1" 3) "mongodb" 4) "2" 5) "mysql" 6) "4"
+
+6、Redis HyperLogLog
+ Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
+'''
\ No newline at end of file
diff --git a/show-me-code/code-04.py b/show-me-code/code-04.py
new file mode 100644
index 0000000..e702cec
--- /dev/null
+++ b/show-me-code/code-04.py
@@ -0,0 +1,60 @@
+'''
+## 第 0004 题: 任一个英文的纯文本文件,统计其中的单词出现的个数。
+'''
+import re, collections
+
+words = re.compile('[a-zA-Z]+')
+def main():
+ with open('./_assets/doc/english.txt', 'r', encoding='utf-8') as f:
+ data = f.read()
+ obj = {}
+ # print(words.findall(data))
+ for word in words.findall(data):
+ if word not in obj:
+ obj[word] = 1
+ else:
+ obj[word] += 1
+ # 统计
+ method1(data)
+ method2(obj)
+
+def method1(data):
+ '''使用包'''
+ frequence_words = collections.Counter(words.findall(data))
+ print(frequence_words)
+
+def method2(data):
+ '''对序列进行操作'''
+ obj_set = list(data.items())
+ obj_sort = sorted(obj_set, key=lambda x: x[1], reverse=True)
+ print(obj_sort)
+
+def method3():
+ pass
+
+if __name__ == '__main__':
+ main()
+
+# 学习 文件操作
+'''
+.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。
+.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。
+另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()。
+'''
+
+# 词频统计
+'''
+collections
+
+
+ OrderedDict类:排序字典,是字典的子类。引入自2.7。
+ namedtuple()函数:命名元组,是一个工厂函数。引入自2.6。
+ Counter类:为hashable对象计数,是字典的子类。引入自2.7。
+ deque:双向队列。引入自2.4。
+ defaultdict:使用工厂函数创建字典,使不用考虑缺失的字典键。引入自2.5。
+
+
+Counter类
+Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。
+collections.Counter(words_box)
+'''
diff --git a/show-me-code/code-05.py b/show-me-code/code-05.py
new file mode 100644
index 0000000..33506e0
--- /dev/null
+++ b/show-me-code/code-05.py
@@ -0,0 +1,140 @@
+'''
+## 第 0005 题: 你有一个目录,装了很多照片,把它们的尺寸变成都不大于 iPhone5 分辨率的大小。
+'''
+from PIL import Image, ImageOps
+import os
+import os.path as path
+
+file_abs_path = r'./_assets/images'
+
+def main():
+ l = os.listdir(file_abs_path)
+ lists = [item for item in l if path.isfile(path.join(file_abs_path,item)) and is_img(item)]
+ print(lists)
+ for filename in lists:
+ filter_img_size(filename)
+
+def filter_img_size(filename):
+ img = Image.open(path.join(file_abs_path, filename))
+ width, height = img.size
+ print(width, height)
+ height = height * 500 // width
+ width = 500
+ img = ImageOps.fit(img, (width, height))
+ w, h = img.size
+ print(w, h)
+ img.save(path.join(r'./dist/05', filename))
+
+def is_img(string):
+ string = string.lower()
+ return string.endswith('.jpg') or string.endswith('png') or string.endswith('.jpeg')
+
+
+if __name__ == '__main__':
+ main()
+
+
+# 学习
+# 注意:
+# 当我使用os.path.isdir(目录的绝对路径)的时候,返回的才是true,也就是说,python的isdir()并不像php的is_dir()那样,可以使用当前工作目录的相对路径,
+'''
+ l = os.listdir('./_assets/images')
+ lists = [item for item in l if os.path.isfile(item)]
+ print(lists) // []
+'''
+
+# 额外知识
+
+'''
+python os 命令
+
+os.sep 可以取代操作系统特定的路径分割符。
+os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
+os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。
+os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
+os.listdir()返回指定目录下的所有文件和目录名。
+os.remove()函数用来删除一个文件。
+os.system()函数用来运行shell命令。
+
+os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'。
+
+os.path.split()函数返回一个路径的目录名和文件名。
+
+os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。
+
+os.path.existe()函数用来检验给出的路径是否真地存在
+
+os和os.path模块
+os.listdir(dirname):列出dirname下的目录和文件
+os.getcwd():获得当前工作目录
+os.curdir:返回但前目录('.')
+os.chdir(dirname):改变工作目录到dirname
+'''
+
+# ImageOps模块的函数
+
+'''
+Image.new(mode,size,color)中,可以填“L”或者‘RGB’等,那么mode这个参数是什么意思呢?
+new方法用于创建一幅给定模式(mode)和尺寸(size)的图片。'RGB'是指的RGB彩色图像,‘L’是指的灰度图像。
+mode 代表如何对图像矩阵进行解析(色彩空间)
+“L”:灰度显示,8bit每像素(区别于1)
+“RGB”:红绿蓝三通道
+
+
+'''
+
+'''
+Autocontrast
+定义:ImageOps.autocontrast(image, cutoff=0)? image
+含义:最大图像对比度。这个函数计算一个输入图像的直方图,从这个直方图中去除最亮和最暗的百分之cutoff,然后重新映射图像,以便保留的最暗像素变为黑色,即0,最亮的变为白色,即255。
+>>> im02 = Image.open("D:\\Code\\Python\\test\\img\\test02.jpg")
+>>> im = ImageOps.autocontrast(im02, 20)
+在图像im02中,去掉了原来直方图中最暗和最亮的各20%,剩下的像素值然后再映射到[0,255]的颜色空间上。
+
+
+Colorize
+ImageOps.colorize(image, black, white)? image
+含义:使得灰色图像变成彩色图像。变量black和white应该是RGB元组或者颜色名称。这个函数会计算出一个颜色值,使得源图像中的所有黑色变成第一种颜色,所有白色变成第二种颜色。
+变量image的模式必须为“L”。
+eg:
+ im_r = ImageOps.colorize(r, "green", "blue")
+
+Crop
+ImageOps.crop(image, border=0)? image
+含义:从图像的四个边去掉变量border定义的四元组对应的行/列。这个函数对所有图像模式有效。
+
+Fit
+ImageOps.fit(image, size, method, bleed, centering)? image
+含义:返回一个指定大小的裁剪过的图像。该图像被裁剪到指定的宽高比和尺寸。变量size是要求的输出尺寸,以像素为单位,是一个(宽,高)元组。
+变量method是用于重采样的方法。默认值为Image.NEAREST。
+变量bleed允许用户去掉图像的边界(图像四个边界)。这个值是一个百分比数(0.01表示百分之一)。默认值是0(没有边界)。
+变量centering用于控制裁剪位置。(0.5,0.5)是裁剪中心(例如,如果裁剪宽度,裁掉左侧50%(右侧50%),顶/底一样)
+
+Flip
+定义:ImageOps.flip(image)? image
+含义:输出图像为输入图像在垂直方向的镜像(顶部跟底部对调)。
+>>> im02= Image.open("D:\\Code\\Python\\test\\img\\test02.jpg")
+>>> im= ImageOps.flip(im02)
+
+Grayscale
+定义:ImageOps.grayscale(image)? image
+含义:将输入图像转换为灰色图像。
+>>>im02 = Image.open("D:\\Code\\Python\\test\\img\\test02.jpg")
+>>> im= ImageOps.grayscale(im02)
+>>>im.mode
+'L'
+
+Invert
+定义:ImageOps.invert(image)? image
+含义:将输入图像转换为反色图像。
+>>>im02 = Image.open("D:\\Code\\Python\\test\\img\\test02.jpg")
+>>> im= ImageOps.invert(im02)
+
+Mirror
+定义:ImageOps.mirror(image)? image
+含义:输出图像为输入图像水平方向的镜像。
+
+Posterize
+定义:ImageOps.posterize(image,bits)? image
+含义:将每个颜色通道上变量bits对应的低(8-bits)个bit置0。变量bits的取值范围为[0,8]。
+'''
\ No newline at end of file
diff --git a/show-me-code/README.md b/show-me-code/show-me-the-code.md
similarity index 98%
rename from show-me-code/README.md
rename to show-me-code/show-me-the-code.md
index 72496ce..78dab44 100644
--- a/show-me-code/README.md
+++ b/show-me-code/show-me-the-code.md
@@ -1,3 +1,5 @@
+# [Show me the code](https://github.com/Yixiaohan/show-me-the-code)
+
## 第 0000 题: 将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果。 类似于图中效果
头像
From aa972cbe52bcbee0993fda322fcb01a85b20f427 Mon Sep 17 00:00:00 2001
From: leeexing <674023427@qq.com>
Date: Wed, 24 Jan 2018 12:43:56 +0800
Subject: [PATCH 02/26] show me the money.006-017
---
show-me-code/code-05.py | 2 +
show-me-code/code-06.py | 23 +++++++++
show-me-code/code-07.py | 59 +++++++++++++++++++++++
show-me-code/code-08.py | 27 +++++++++++
show-me-code/code-09.py | 29 +++++++++++
show-me-code/code-10.py | 30 ++++++++++++
show-me-code/code-11.py | 103 ++++++++++++++++++++++++++++++++++++++++
show-me-code/code-12.py | 43 +++++++++++++++++
show-me-code/code-13.py | 57 ++++++++++++++++++++++
show-me-code/code-14.py | 62 ++++++++++++++++++++++++
show-me-code/code-17.py | 30 ++++++++++++
11 files changed, 465 insertions(+)
create mode 100644 show-me-code/code-06.py
create mode 100644 show-me-code/code-07.py
create mode 100644 show-me-code/code-08.py
create mode 100644 show-me-code/code-09.py
create mode 100644 show-me-code/code-10.py
create mode 100644 show-me-code/code-11.py
create mode 100644 show-me-code/code-12.py
create mode 100644 show-me-code/code-13.py
create mode 100644 show-me-code/code-14.py
create mode 100644 show-me-code/code-17.py
diff --git a/show-me-code/code-05.py b/show-me-code/code-05.py
index 33506e0..ac728d9 100644
--- a/show-me-code/code-05.py
+++ b/show-me-code/code-05.py
@@ -62,6 +62,8 @@ def is_img(string):
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。
+ os.path.splitext(path) 分离文件名与扩展名;默认返回(fname,fextension)元组,可做分片操作
+
os.path.existe()函数用来检验给出的路径是否真地存在
os和os.path模块
diff --git a/show-me-code/code-06.py b/show-me-code/code-06.py
new file mode 100644
index 0000000..2895ff8
--- /dev/null
+++ b/show-me-code/code-06.py
@@ -0,0 +1,23 @@
+'''
+## 第 0006 题: 你有一个目录,放了你一个月的日记,都是 txt,为了避免分词的问题,假设内容都是英文,请统计出你认为每篇日记最重要的词。
+'''
+import re, os, collections
+
+word = re.compile('\w+')
+path_file = r'./_assets/doc'
+def main():
+ files = os.listdir(path_file)
+ print(files)
+ obj = {}
+ for filename in files:
+ with open(os.path.join(path_file, filename), encoding='utf-8') as f:
+ data = f.read()
+ words = word.findall(data)
+ words_freq = list(sorted(collections.Counter(words).items(), key = lambda x: x[1], reverse = True))
+ # print(words_freq)
+ obj[filename] = words_freq[0]
+ print(obj)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/show-me-code/code-07.py b/show-me-code/code-07.py
new file mode 100644
index 0000000..12bc4da
--- /dev/null
+++ b/show-me-code/code-07.py
@@ -0,0 +1,59 @@
+'''
+## 第 0007 题: 有个目录,里面是你自己写过的程序,统计一下你写过多少行代码。包括空行和注释,但是要分别列出来。
+'''
+import re
+import os
+
+path_file = r'./_assets/code'
+ret = {}
+
+def main():
+ files_names = []
+ files = [f for f in os.walk(path_file)]
+ for f in files:
+ path_head = f[0].replace('\\', '/')
+ files_f = [(path_head + '/' + item) for item in f[2]]
+ files_names.extend(files_f)
+ print(files_names)
+ counter_code(files_names[4:5])
+
+def counter_code(filenames):
+ '''统计代码行数'''
+ docu_flag = False
+ for item in filenames:
+ ret[item] = 0
+ with open(item, 'r', encoding='utf-8') as f:
+ lines = f.readlines()
+ for line in lines:
+ line = line.strip()
+ if line.startswith(r'//') or line.startswith(r'#'):
+ print(line)
+ continue
+ if line.startswith(r'/*') and line.endswith(r'*/'):
+ print(line)
+ continue
+ if line.startswith(r'/*') and not line.endswith(r'*/'):
+ print(line)
+ docu_flag = True
+ continue
+ if not line.startswith(r'/*') and line.endswith(r'*/'):
+ print(line)
+ docu_flag = False
+ continue
+ if line != '' and docu_flag:
+ print(line)
+ else:
+ ret[item] += 1
+ # print(line, end='')
+ print('='*20)
+ print(ret)
+
+def get_files(pathname):
+ files = os.listdir(path_file)
+ return [x for x in files if is_file(x)]
+
+def is_file(path_name):
+ return os.path.isfile(os.path.join(path_file, path_name))
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/show-me-code/code-08.py b/show-me-code/code-08.py
new file mode 100644
index 0000000..998e259
--- /dev/null
+++ b/show-me-code/code-08.py
@@ -0,0 +1,27 @@
+'''
+## 第 0008 题: 一个HTML文件,找出里面的正文。
+'''
+import re, os
+import requests
+from bs4 import BeautifulSoup
+
+path_file = r'./_assets/code'
+def main():
+ names = [os.path.join(path_file, item) for item in os.listdir(path_file) if item.endswith('.html')]
+ print(names)
+ for item in names[1:2]:
+ with open(item, encoding='utf-8') as f:
+ data = f.read()
+ print(data)
+
+def app():
+ url = 'http://www.leeeing.com/'
+ content = requests.get(url).content
+ # print(content.decode('utf-8'))
+ soup = BeautifulSoup(content, 'html.parser')
+ body = soup.select('body')[0]
+ print(body.get_text())
+
+if __name__ == '__main__':
+ # main()
+ app()
\ No newline at end of file
diff --git a/show-me-code/code-09.py b/show-me-code/code-09.py
new file mode 100644
index 0000000..ec74232
--- /dev/null
+++ b/show-me-code/code-09.py
@@ -0,0 +1,29 @@
+'''
+## 第 0009 题: 一个HTML文件,找出里面的链接。
+'''
+import re, os
+import requests
+from bs4 import BeautifulSoup
+
+path_file = r'./_assets/code'
+def main():
+ names = [os.path.join(path_file, item) for item in os.listdir(path_file) if item.endswith('.html')]
+ print(names)
+ for item in names[1:2]:
+ with open(item, encoding='utf-8') as f:
+ data = f.read()
+ print(data)
+
+def app():
+ url = 'http://www.leeeing.com/'
+ content = requests.get(url).content
+ # print(content.decode('utf-8'))
+ soup = BeautifulSoup(content, 'html.parser')
+ links = soup.select('a')
+ for item in links:
+ print(item.get_text().strip())
+ # print(link.get_text())
+
+if __name__ == '__main__':
+ # main()
+ app()
\ No newline at end of file
diff --git a/show-me-code/code-10.py b/show-me-code/code-10.py
new file mode 100644
index 0000000..4c74fa1
--- /dev/null
+++ b/show-me-code/code-10.py
@@ -0,0 +1,30 @@
+'''
+## 第 0010 题: 使用 Python 生成类似于下图中的字母验证码图片
+'''
+from PIL import Image, ImageFont, ImageOps, ImageDraw
+import string
+import random
+
+forSelect = string.ascii_letters + '0123456789'
+
+def main():
+ width = 60 * 4
+ height = 60
+ img = Image.new('RGB', (width, height), (255, 255, 255))
+ font = ImageFont.truetype('./_assets/ttf/arialuni.ttf', 50)
+ draw = ImageDraw.Draw(img)
+ for x in range(width):
+ for y in range(height):
+ draw.point((x,y), fill = rand_color())
+ for t in range(4):
+ draw.text((60*t + 10, 0), random.choice(forSelect), font = font, fill = rand_color2())
+ img.show()
+
+def rand_color():
+ return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
+
+def rand_color2():
+ return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/show-me-code/code-11.py b/show-me-code/code-11.py
new file mode 100644
index 0000000..cfd7ae9
--- /dev/null
+++ b/show-me-code/code-11.py
@@ -0,0 +1,103 @@
+'''
+## 第 0011 题: 敏感词文本文件 filtered_words.txt,里面的内容为以下内容,当用户输入敏感词语时,则打印出 Freedom,否则打印出 Human Rights。
+
+北京
+程序员
+公务员
+领导
+牛比
+牛逼
+你娘
+你妈
+love
+sex
+jiangge
+'''
+import os
+
+path_file = r'./_assets/doc'
+
+word_filter = set()
+
+def main():
+ global word_filter
+ with open(os.path.join(path_file, 'filter_words.txt'), 'r', encoding='utf-8') as f:
+ data = f.readlines()
+ for item in data:
+ if item.strip() != '':
+ word_filter |= {item.strip('\n')}
+ print(word_filter)
+ please_input()
+
+
+def please_input():
+ '''这是一个输入交互'''
+ while True:
+ s = input()
+ if s == 'exit':
+ break
+ elif s in word_filter:
+ print('Freedom')
+ else:
+ print('Human Rights')
+
+if __name__ == '__main__':
+ main()
+
+# 学习
+# set : 是一个无序不重复元素集。
+# **注意**:是无序的。顺序是无可预知!!
+'''
+集合支持一系列标准操作,包括并集、交集、差集和对称差集,例如:
+
+a = t | s # t 和 s的并集 # 相当于 s.update(t)
+
+b = t & s # t 和 s的交集
+
+c = t – s # 求差集(项在t中,但不在s中)
+
+d = t ^ s # 对称差集(项在t或s中,但不会同时出现在二者中)
+
+基本操作:
+
+t.add('x') # 添加一项
+
+s.update([10,37,42]) # 在s中添加多项
+
+使用remove()可以删除一项:
+t.remove('H')
+
+s.discard(x)
+如果在 set “s”中存在元素 x, 则删除
+
+s.pop()
+删除并且返回 set “s”中的一个不确定的元素, 如果为空则引发 KeyError
+
+s.clear()
+删除 set “s”中的所有元素
+
+len(s)
+set 的长度
+
+x in s
+测试 x 是否是 s 的成员
+
+s.issubset(t)
+s <= t
+测试是否 s 中的每一个元素都在 t 中
+
+s.issuperset(t)
+s >= t
+测试是否 t 中的每一个元素都在 s 中
+
+s.union(t)
+s | t
+返回一个新的 set 包含 s 和 t 中的每一个元素
+
+hash(s)
+返回 s 的 hash 值
+
+s.copy()
+返回 set “s”的一个浅复制
+
+'''
\ No newline at end of file
diff --git a/show-me-code/code-12.py b/show-me-code/code-12.py
new file mode 100644
index 0000000..b1347f1
--- /dev/null
+++ b/show-me-code/code-12.py
@@ -0,0 +1,43 @@
+'''
+## 第 0012 题: 敏感词文本文件 filtered_words.txt,里面的内容 和 0011题一样,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成「**是个好城市」。
+'''
+import os
+
+path_file = './_assets/doc'
+
+sensitive_words = set()
+
+def main():
+ global sensitive_words
+ with open(os.path.join(path_file, 'filter_words.txt'), encoding='utf-8') as f:
+ lines = f.readlines()
+ for line in lines:
+ line = line.strip()
+ if line != '':
+ sensitive_words.update({line})
+ # sensitive_words |= {line}
+ print(sensitive_words)
+ civilization()
+
+def civilization():
+ '''文明'''
+ while True:
+ word = input()
+ info = is_sensive_in_words(word)
+ print(info)
+ if word == 'exit':
+ break
+ elif info[0]:
+ print(word.replace(info[1], '*'*(len(info[1]))))
+
+def is_sensive_in_words(word):
+ '''是否包含敏感词'''
+ print(word)
+ for item in sensitive_words:
+ if item in word:
+ return True, item
+ continue
+ return False, 0
+
+if __name__ == '__main__':
+ main()
diff --git a/show-me-code/code-13.py b/show-me-code/code-13.py
new file mode 100644
index 0000000..523552a
--- /dev/null
+++ b/show-me-code/code-13.py
@@ -0,0 +1,57 @@
+'''
+## 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-)
+http://tieba.baidu.com/p/2166231880
+'''
+import requests
+from bs4 import BeautifulSoup
+from urllib.request import urlretrieve
+
+def get_image_srcs(url):
+ content = requests.get(url).content
+ # print(content.decode('utf-8'))
+ soup = BeautifulSoup(content, 'lxml')
+ images = soup.select('.p_content img')
+ print(len(images))
+ img_srcs = []
+ for img in images:
+ src = img.attrs['src']
+ img_srcs.append(src)
+ return img_srcs
+
+def get_image(index, url):
+ bdwater = '杉本有美吧'
+ img_r = requests.get(url, stream = True)
+ if img_r.status_code == 200:
+ with open('./dist/013/{}-{}.jpg'.format(bdwater, index), 'wb') as f:
+ for chunk in img_r:
+ f.write(chunk)
+
+def get_img_by_uillib(index, url):
+ '''这个方法更加简单,一部就可以搞定'''
+ urlretrieve(url, './dist/013/杉本有美吧-{}.jpg'.format(index))
+
+def main():
+ url = 'http://tieba.baidu.com/p/2166231880'
+ img_srcs = get_image_srcs(url)
+
+ # 方法一
+ # for index, src in enumerate(img_srcs, 1):
+ # get_image(index, src)
+
+ # 方法二
+ for index, src in enumerate(img_srcs[0:5], 1):
+ get_img_by_uillib(index, src)
+
+if __name__ == '__main__':
+ main()
+
+
+# 学习
+
+# enumerate()使用
+'''
+enumerate()是python的内置函数
+enumerate在字典上是枚举、列举的意思
+对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得 索引和值 -- 重点
+enumerate多用于在for循环中得到计数
+'''
\ No newline at end of file
diff --git a/show-me-code/code-14.py b/show-me-code/code-14.py
new file mode 100644
index 0000000..29cba8c
--- /dev/null
+++ b/show-me-code/code-14.py
@@ -0,0 +1,62 @@
+'''
+## 第 0014 题: 纯文本文件 student.txt为学生信息, 里面的内容(包括花括号)如下所示:
+
+{
+ "1":["张三",150,120,100],
+ "2":["李四",90,99,95],
+ "3":["王五",60,66,68]
+}
+请将上述内容写到 student.xls 文件中,如下图所示:
+
+student.xls
+
+阅读资料 腾讯游戏开发 XML 和 Excel 内容相互转换
+'''
+
+import xlwt
+import re
+
+def main():
+ fname = './dist/014/student.xls'
+ book = xlwt.Workbook(encoding='utf-8', style_compression=0)
+ sheet = book.add_sheet('student', cell_overwrite_ok = True)
+ info = re.compile(r'\"(\d+)\":\[\"(\w+)\",(\d+),(\d+),(\d+)\]')
+
+ with open('./_assets/doc/student.txt', 'r', encoding='utf-8') as f:
+ txt = f.read()
+ print(txt)
+ print(info.findall(txt))
+ data = info.findall(txt)
+ for row_ind, line in enumerate(data):
+ for col_ind, cell in enumerate(line):
+ sheet.write(row_ind, col_ind, cell)
+
+ book.save(fname)
+
+if __name__ == '__main__':
+ main()
+
+
+# 学习
+
+# python操作Excel读写
+
+'''
+处理excel文件是在工作中经常用到的,python为我们考虑到了这一点,python中本身就自带csv模块。
+
+创建工作簿(workbook)和工作表(sheet)
+import xlwt
+workbook = xlwt.Workbook()
+sheet = workbook.add_sheet("Sheet Name")
+
+写单元格(cell)
+sheet.write(0, 0, 'foobar') # row, column, value
+
+对单元格应用样式(加粗为例)
+style = xlwt.easyxf('font: bold 1')
+sheet.write(0, 0, 'foobar', style)
+
+设置列宽
+sheet.col(0).width = 256 * (len(key) + 1)
+# set width.. 256 = 1 width of 0 character
+'''
\ No newline at end of file
diff --git a/show-me-code/code-17.py b/show-me-code/code-17.py
new file mode 100644
index 0000000..2796a72
--- /dev/null
+++ b/show-me-code/code-17.py
@@ -0,0 +1,30 @@
+'''
+## 第 0017 题: 将 第 0014 题中的 student.xls 文件中的内容写到 student.xml 文件中,如
+
+下所示:
+
+
+
+
+
+{
+ "1" : ["张三", 150, 120, 100],
+ "2" : ["李四", 90, 99, 95],
+ "3" : ["王五", 60, 66, 68]
+}
+
+
+'''
+
+import xlrd
+import re
+
+def main():
+ fname = './dist/014/student.xls'
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
From 1fd5010186b5563c61271074a41fad5c53b6a76c Mon Sep 17 00:00:00 2001
From: leeexing <674023427@qq.com>
Date: Thu, 25 Jan 2018 19:07:03 +0800
Subject: [PATCH 03/26] show me the code 17 to 21
---
show-me-code/code-17.py | 91 ++++++++++++++++++++++++++++++++++++++--
show-me-code/code-18.py | 17 ++++++++
show-me-code/code-20.py | 4 ++
show-me-code/code-21.py | 68 ++++++++++++++++++++++++++++++
show-me-code/student.xml | 2 +
5 files changed, 179 insertions(+), 3 deletions(-)
create mode 100644 show-me-code/code-18.py
create mode 100644 show-me-code/code-20.py
create mode 100644 show-me-code/code-21.py
create mode 100644 show-me-code/student.xml
diff --git a/show-me-code/code-17.py b/show-me-code/code-17.py
index 2796a72..833b132 100644
--- a/show-me-code/code-17.py
+++ b/show-me-code/code-17.py
@@ -19,12 +19,97 @@
'''
-import xlrd
-import re
+import xlrd, codecs
+from lxml import etree
+from collections import OrderedDict
+
+def read_xls(filename):
+ data = xlrd.open_workbook(filename)
+ table = data.sheets()[0]
+ print(table.nrows)
+ c = OrderedDict()
+ for idx in range(table.nrows):
+ print(table.row_values(idx))
+ print(table.cell(idx,0).value)
+ c[table.cell(idx, 0).value] = table.row_values(idx)[1:]
+ return c
+
+def save_xml(data):
+ output = codecs.open('student.xml', 'w', 'utf-8')
+ root = etree.Element('root')
+ student_xml = etree.ElementTree(root)
+ student = etree.SubElement(root, 'student')
+ student.text = str(data)
+ student.append(etree.Comment('学生信息表\n\"id\": [名字, 数学,语文, 英语]'))
+ output.write(etree.tounicode(student_xml.getroot()))
+ output.close()
def main():
fname = './dist/014/student.xls'
+ data = read_xls(fname)
+ print(data)
+ save_xml(data)
if __name__ == '__main__':
- main()
\ No newline at end of file
+ main()
+
+# 学习
+
+# OrderedDict
+# Python中的字典对象可以以“键:值”的方式存取数据。OrderedDict是它的一个子类,实现了对字典对象中元素的排序。
+# 使用OrderedDict会根据放入元素的先后顺序进行排序。由于进行了排序,所以OrderedDict对象的字典对象,如果其顺序不同那么Python也会把他们当做是两个不同的对象
+'''
+一、首先明白创建 dict 的方式
+
+1、传统的文字表达式:
+>>> d={'name':'Allen','age':21,'gender':'male'}
+>>> d
+{'age': 21, 'name': 'Allen', 'gender': 'male'}
+
+2.动态分配键值:
+>>> d={}
+>>> d['name']='Allen'
+>>> d['age']=21
+>>> d['gender']='male'
+>>> d
+{'age': 21, 'name': 'Allen', 'gender': 'male'}
+
+3.字典键值表:
+>>> c = dict(name='Allen', age=14, gender='male')
+>>> c
+{'gender': 'male', 'name': 'Allen', 'age': 14}
+
+**注意**
+因为这种形式语法简单,不易出错,所以非常流行。
+这种形式所需的代码比常量少,但是键必须都是字符串才行,所以下列代码会报错
+>>> c = dict(name='Allen', age=14, gender='male', 1='abcd')
+SyntaxError: keyword can't be an expression
+
+4.字典键值元组表
+>>> obj = dict([('1', ['张三', '150', '120', '100']), ('name','Allen')])
+>>> obj
+{'1': ['张三', '150', '120', '100']}
+ 如果你需要在程序运行时把键和值逐步建成序列,那么这种方式比较有用。
+
+# 这种数据格式就是和 obj.items() 返回的数据格式相同
+
+5.所有键的值都相同或者赋予初始值:
+>>> f=dict.fromkeys(['height','weight'],'normal')
+>>> f
+{'weight': 'normal', 'height': 'normal'}
+
+二、collections.OrderedDict
+
+dd = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
+#按key排序
+kd = collections.OrderedDict(sorted(dd.items(), key=lambda t: t[0]))
+print kd
+#按照value排序
+vd = collections.OrderedDict(sorted(dd.items(),key=lambda t:t[1]))
+print vd
+
+#输出
+OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
+OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
+'''
\ No newline at end of file
diff --git a/show-me-code/code-18.py b/show-me-code/code-18.py
new file mode 100644
index 0000000..5cfadf9
--- /dev/null
+++ b/show-me-code/code-18.py
@@ -0,0 +1,17 @@
+'''
+## 第 0018 题: 将 ## 第 0015 题中的 city.xls 文件中的内容写到 city.xml 文件中,如下 所示:
+
+
+
+
+
+ {
+ "1" : "上海",
+ "2" : "北京",
+ "3" : "成都"
+ }
+
+
+'''
\ No newline at end of file
diff --git a/show-me-code/code-20.py b/show-me-code/code-20.py
new file mode 100644
index 0000000..9c39c4b
--- /dev/null
+++ b/show-me-code/code-20.py
@@ -0,0 +1,4 @@
+'''
+## 第 0020 题: 登陆中国联通网上营业厅 后选择「自助服务」 --> 「详单查询」,然后选择你要查询的时间段,
+# 点击「查询」按钮,查询结果页面的最下方,点击「导出」,就会生成类似于 2014年10月01日~2014年10月31日通话详单.xls 文件。写代码,对每月通话时间做个统计。
+'''
\ No newline at end of file
diff --git a/show-me-code/code-21.py b/show-me-code/code-21.py
new file mode 100644
index 0000000..afdca64
--- /dev/null
+++ b/show-me-code/code-21.py
@@ -0,0 +1,68 @@
+'''
+## 第 0021 题: 通常,登陆某个网站或者 APP,需要使用用户名和密码。密码是如何加密后存储起来的呢?请使用 Python 对密码加密。
+'''
+import hashlib
+from collections import defaultdict
+
+# db = {}
+db = defaultdict(lambda: 'N/A')
+
+def get_md5(password):
+ a = hashlib.md5()
+ a.update(password.encode('utf-8'))
+ return (a.hexdigest())
+
+def register(username, password):
+ db[username] = get_md5(password + username + 'the-Salt')
+
+def login(username, password):
+ b = get_md5(password + username + 'the-Salt')
+ print(b)
+ if b == db[username]:
+ return True
+ else:
+ return False
+
+def app():
+ a = input('注册输入用户名:')
+ b = input('注册输入密码:')
+ register(a, b)
+
+ while True:
+ c = input('登陆输入用户名:')
+ if c == 'exit':
+ break
+ d = input('登陆输入密码:')
+ if login(c, d):
+ print('{:+^20}'.format('登陆成功'))
+ else:
+ print('{:=^20}'.format('登陆失败'))
+
+def main():
+ app()
+
+if __name__ == '__main__':
+ main()
+
+# 学习
+
+# defaultdict
+
+'''
+用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的顺序。
\ No newline at end of file
diff --git a/show-me-code/student.xml b/show-me-code/student.xml
new file mode 100644
index 0000000..971e106
--- /dev/null
+++ b/show-me-code/student.xml
@@ -0,0 +1,2 @@
+OrderedDict([('1', ['张三', '150', '120', '100']), ('2', ['李四', '90', '99', '95']), ('3', ['王五', '60', '66', '68'])])
\ No newline at end of file
From cbb97d22079fc965701cd1b995bbb9211fdf433b Mon Sep 17 00:00:00 2001
From: leeexing <674023427@qq.com>
Date: Fri, 26 Jan 2018 17:52:55 +0800
Subject: [PATCH 04/26] show me the code finish 70.but need time to digestion
---
show-me-code/code-22.py | 33 ++++++++++++++++++
show-me-code/code-23.py | 63 ++++++++++++++++++++++++++++++++++
show-me-code/oodes/code-001.py | 27 +++++++++++++++
3 files changed, 123 insertions(+)
create mode 100644 show-me-code/code-22.py
create mode 100644 show-me-code/code-23.py
create mode 100644 show-me-code/oodes/code-001.py
diff --git a/show-me-code/code-22.py b/show-me-code/code-22.py
new file mode 100644
index 0000000..d82fd02
--- /dev/null
+++ b/show-me-code/code-22.py
@@ -0,0 +1,33 @@
+'''
+## 第 0022 题: iPhone 6、iPhone 6 Plus 早已上市开卖。请查看你写得 ## 第 0005 题的代码是否可以复用
+'''
+from PIL import Image
+import os
+
+path_file = './_assets/images'
+
+def self_adaption(files, width, height):
+ for fname in files:
+ img = Image.open(os.path.join(path_file, fname))
+ print('{} 图像的原始宽:{} - 高:{} - 类型:{}'.format(fname, img.size[0], img.size[1], img.mode))
+ img.thumbnail((width, height))
+ print('{} 图像缩放后的宽高:{} - {} - {}'.format(fname, img.size[0], img.size[1], img.mode))
+ print('='*20)
+ # img.show()
+ img.save(os.path.join('./dist/022', fname))
+
+def main():
+ files = [fs for fs in os.listdir(path_file) if os.path.isfile(os.path.join(path_file, fs)) and fs.endswith('.jpg')]
+ PHONE = {
+ 'iphone5': (1136, 640),
+ 'iphone6': (1134,750),
+ 'iphone6P': (2208, 1242)
+ }
+ width, height = PHONE['iphone6']
+ print(files)
+ self_adaption(files, width, height)
+
+if __name__ == '__main__':
+ main()
+
+# 学习
\ No newline at end of file
diff --git a/show-me-code/code-23.py b/show-me-code/code-23.py
new file mode 100644
index 0000000..045fa97
--- /dev/null
+++ b/show-me-code/code-23.py
@@ -0,0 +1,63 @@
+'''
+## 第 0023 题: 使用 Python 的 Web 框架,做一个 Web 版本 留言簿 应用。
+
+阅读资料:Python 有哪些 Web 框架
+
+留言簿参考
+'''
+from flask import Flask
+from sqlalchemy import String, DATETIME, Interger, Column
+
+app = Flask(__name__)
+
+class Post(base):
+ __tablename__ = 'todo'
+
+ postID = Column(Interge, primary_key=True)
+ postName = Column(String(50))
+ createdAt = Column(DATETIME)
+ content = Column(String(15000))
+
+class DataBase(object):
+ def __init__(self):
+ self.info = {
+ 'uesr': '',
+ 'password': '',
+ 'ip': '',
+ 'port': '',
+ 'database': ''
+ }
+ self.session = self.make_connect()
+
+ def __del__(self):
+ if self.session:
+ self.session.close()
+
+ def make_connect(self):
+ connect_str = 'mysql + pymysql: //{user}:{password}@{ip}:{port}/{database}'.format(self.info)
+ engine = create_engine(connect_str)
+ DBSession = sessionmaker(engine)
+ session = DBSession()
+ return session
+
+ def query_all_post(self):
+ items = self.session.query(Post).order_by(Post.postID).all()
+ if not isinstance(items, list):
+ return [items]
+ return items
+
+ def add_post(self, item):
+ self.session.add(item)
+ self.session.commit()
+
+
+@app.route('/', methods=['GET'])
+def index():
+ pass
+
+@app.route('/add', methods=['POST','GET'])
+def add():
+ pass
+
+if __name__ == '__main__':
+ app.run(debug=True)
\ No newline at end of file
diff --git a/show-me-code/oodes/code-001.py b/show-me-code/oodes/code-001.py
new file mode 100644
index 0000000..a717187
--- /dev/null
+++ b/show-me-code/oodes/code-001.py
@@ -0,0 +1,27 @@
+# 第 0001 题:做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),
+# 使用 Python 如何生成 200 个激活码(或者优惠券)?
+
+import string
+import random
+
+KEY_LEN = 20
+KEY_ALL = 200
+
+KEY_STRING = string.ascii_letters + string.digits
+
+def key_gen():
+ keylists = [random.choice(KEY_STRING) for _ in range(KEY_LEN)]
+ return ''.join(keylists)
+
+def key_num(num, result=None):
+ if result is None:
+ result = []
+ for _ in range(num):
+ result.append(key_gen())
+ return result
+
+def main():
+ print(key_num(10))
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
From 85312aa5269d3faccef5a96daa30a3742f5ca60d Mon Sep 17 00:00:00 2001
From: leeexing
Date: Thu, 1 Feb 2018 20:08:49 +0800
Subject: [PATCH 05/26] modify from ubuntu.
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 6ce0a89..92e6ac9 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+Bfdhfdf
+
+B
+B
> "What I cannot create, I do not understand."
> -- Richard Feynman
@@ -72,4 +76,4 @@
some crawler demos
## reading
- read some python books and some of my thoughts
\ No newline at end of file
+ read some python books and some of my thoughts
From 2563312355270af72cdc3f0e15dc336556d7cba1 Mon Sep 17 00:00:00 2001
From: leeexing <674023427@qq.com>
Date: Sun, 4 Feb 2018 10:55:27 +0800
Subject: [PATCH 06/26] add douban.py file to spider some data to my blog
---
books/git.md | 17 +++++++++-
crawler/crawler.md | 19 ++++++++++++
crawler/douban/demo.py | 10 ++++++
crawler/douban/music.py | 47 +++++++++++++++++++++++-----
crawler/wangyi/1.mp3 | Bin 0 -> 4119536 bytes
crawler/wangyi/spider163.py | 60 ++++++++++++++++++++++++++++++++++++
6 files changed, 144 insertions(+), 9 deletions(-)
create mode 100644 crawler/crawler.md
create mode 100644 crawler/douban/demo.py
create mode 100644 crawler/wangyi/1.mp3
create mode 100644 crawler/wangyi/spider163.py
diff --git a/books/git.md b/books/git.md
index daaf243..12382c6 100644
--- a/books/git.md
+++ b/books/git.md
@@ -158,4 +158,19 @@ warning: Your console font probably doesn't support Unicode. If you experience s
## 如何检测 当前分支与远程分支存在追踪关系
如何查看当前分支如temp,track到的是远程代码库的哪个分支呀?
- git config -l | grep 'branch\.temp'
\ No newline at end of file
+ git config -l | grep 'branch\.temp'
+
+
+## git log
+
+### 1、git log
+
+### 2、git log -p -2
+
+### 3、git log --stat
+
+```js
+在做代码审查,或者要快速浏览其他协作者提交的更新都作了哪些改动时,就可以用这个选项。此外,还有许多摘要选项可以用,比如 --stat,仅显示简要的增改行数统计:
+```
+
+### 4、git log --pretty=oneline
\ No newline at end of file
diff --git a/crawler/crawler.md b/crawler/crawler.md
new file mode 100644
index 0000000..a80c540
--- /dev/null
+++ b/crawler/crawler.md
@@ -0,0 +1,19 @@
+# crawler
+
+> 爬虫也不是那么简单啦
+
+## 编码问题
+
+1、一般情况下是不需要改动默认的编码格式的
+
+```python
+import io
+import sys
+# 改变默认的编码方式sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
+sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030'
+```
+
+因为有些网页默认的编码方式就是 `utf-8`,使用了上面的代码修改默认的编码格式之后,反而会造成网页的部分汉字显示出现乱码的现象
+正确的做法就应该是 先不要一上来就使用修改默认的方式,先输出查看,如果是有乱码问题存在,再使用之
+
+2、
\ No newline at end of file
diff --git a/crawler/douban/demo.py b/crawler/douban/demo.py
new file mode 100644
index 0000000..98ccbf4
--- /dev/null
+++ b/crawler/douban/demo.py
@@ -0,0 +1,10 @@
+import requests
+import json
+
+def main():
+ data = requests.get('http://v3.wufazhuce.com:8000/api/channel/reading/more/0').content
+
+ print(json.loads(data))
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/crawler/douban/music.py b/crawler/douban/music.py
index c3ad20b..be1007d 100644
--- a/crawler/douban/music.py
+++ b/crawler/douban/music.py
@@ -1,14 +1,23 @@
+# encoding = 'utf-8
'''
爬虫豆瓣音乐
'''
import re, requests, time
from bs4 import BeautifulSoup
-import io, sys
+import json
import pymongo
# 修改默认编码方式
-sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030')
-def get_music(url):
+client = pymongo.MongoClient('localhost', 27017)
+douban = client['myblog']['music']
+
+nums = re.compile('\d+')
+
+music_categories = ['古典', '轻音乐','电子', '民谣', '爵士', '流行', '说唱']
+
+music_arr = []
+
+def get_music(url, category):
''' no '''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
@@ -19,13 +28,35 @@ def get_music(url):
}
content = requests.get(url, headers=headers).content
soup = BeautifulSoup(content, 'lxml')
+ photoins = soup.select('.photoin')
+ for photo in photoins:
+ obj = {
+ 'type': category,
+ 'typeName': music_categories[category-1],
+ 'cover': photo.select('.artist-img .artist_photo img')[0].attrs['src'],
+ 'href': photo.select('.artist-img .artist_photo')[0].attrs['href'],
+ 'sides': json.loads(photo.select('.artist-img')[0].attrs['data-sids']),
+ 'name': photo.select('.ll a')[0].get_text(),
+ 'like': int(nums.findall(photo.select('.ll .pl')[0].get_text())[0])
+ }
+ music_arr.append(obj)
-
+def save_music(item):
+ if douban.save(item):
+ pass
+ else:
+ print('保存失败')
+
def main():
- urls = ['https://music.douban.com/artists/genre_page/6/{}'.format(url) for url in range(1,6)]
- for url in urls:
- get_music(url)
- time.sleep(1)
+ # urls = ['https://music.douban.com/artists/genre_page/{}/{}'.format(cate, indx) for cate in range(1, 2) for indx in range(1,2)]
+ for cate in range(1, 8):
+ for index in range(1, 6):
+ get_music('https://music.douban.com/artists/genre_page/{}/{}'.format(cate, index), cate)
+ time.sleep(1)
+ # print(music_arr)
+ for item in music_arr:
+ save_music(item)
+
if __name__ == "__main__":
main()
\ No newline at end of file
diff --git a/crawler/wangyi/1.mp3 b/crawler/wangyi/1.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..31c49008a80e9302260664319e6154065d464c65
GIT binary patch
literal 4119536
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%0AAw{&xfoIGo4?=IhYFR$$7fhGd
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
U{Bb<9IbZ>6cWArQ=EwJG)XsYRQDfMQ
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