新手向:十個趣味性Python腳本

在簡書上發現一個特別好玩的作者,個人簽名 = "戰戰兢兢"*3 。今天分享一篇ta的文章,使用Python寫成的腳本,簡單有趣,適合新手練習。

原文在這裡:用Python寫有趣的腳本

01. 目錄文件分類

前言

有時候,想要對一個目錄里的文件進行搜索或者分類操作往往是一件痛苦的事情,下面這個程序的目的是將目錄下的文件樹以某種分類規則進行排列。

用法

usage: classify.py [-h] [-t {ext,mtime,back}] directory對目錄進行文件整理歸類.positional arguments: directory 目標目錄路徑optional arguments: -h, --help show this help message and exit -t {ext,mtime,back}, --type {ext,mtime,back} 分類方式

按擴展名分類

python classify.py -t ext 目錄路徑

效果:

├── DS_Store├── bat├── bin├── css├── db├── default├── gif├── gitattributes├── gitignore├── htaccess├── jar├── js├── json├── lib├── log├── md├── php├── plex├── png├── sql├── sublime-project├── sublime-workspace├── tpl├── txt├── xml├── y└── yml

按修改時間分類

python classify.py -t mtime 目錄路徑

效果:

├── 2014│ └── 10│ └── 24├── 2015│ └── 12│ └── 21└── 2016 ├── 6 │ ├── 28 │ ├── 29 │ └── 30 ├── 7 │ ├── 1 │ └── 26 └── 8 ├── 6 └── 7

按首字母/數字分類

python classify.py -t word 目錄路徑

效果:

├── 3├── 4├── 5├── N├── R├── W├── a├── b├── c├── d├── e├── f├── h├── i├── j├── l├── m├── o├── p├── s├── t├── u├── v└── y

還原目錄

python classify.py -t back 目錄路徑

效果:

├── assets│ ├── 2e015166│ ├── 4893405d│ │ ├── detailview│ │ ├── gridview│ │ └── listview│ ├── 4a5213fe│ └── a2744ecd│ ├── autocomplete│ ├── jui│ │ ├── css│ │ │ └── base│ │ │ └── images│ │ └── js│ ├── rating│ ├── treeview│ │ └── images│ └── yiitab├── css├── protected│ ├── commands│ ├── components│ ├── config│ ├── controllers│ ├── data│ ├── extensions│ │ └── smarty│ │ ├── demo│ │ │ ├── plugins│ │ │ └── templates│ │ ├── lexer│ │ └── libs│ │ ├── plugins│ │ └── sysplugins│ ├── filters│ ├── messages│ │ └── zh_cn│ ├── models│ ├── runtime│ ├── sql_source│ ├── tests│ │ ├── functional│ │ └── unit│ └── views│ ├── blog│ ├── layouts│ ├── login│ ├── postadmin│ └── useradmin└── themes └── classic └── views

源碼

#!/usr/bin/python #-*- coding:utf-8 -*- import argparseimport osimport jsonimport shutilimport sysimport timefrom uuid import uuid4DEFAULT_KEY = "default"BACKUP_FILE = ".backup.json" # 防止遷移的時候出現文件重名的情況 def unique_covert(file_path): new_path = "|".join(file_path.split(os.sep)[:-1]) if not new_path: return file_path return os.path.basename(file_path) + " (" + new_path + ")" def coroutine(gen): def wrapper(*arg, **kws): coroutine = gen(*arg, **kws) next(coroutine) return coroutine return wrapper@coroutine def save_back_up(target_dir): string_len = len(target_dir) back_up_file = os.path.join(target_dir, BACKUP_FILE) if os.path.exists(back_up_file): go_back(target_dir) back_up_tree = {} while True: tup = yield if not tup: break (now, prev) = tup back_up_tree[now] = prev with open(back_up_file, "w") as buf: json.dump(back_up_tree, buf, indent=4) # 按擴展名分類 def classify_by_ext(target_dir, tmp_dir): from collections import defaultdict ext_files = defaultdict(list) for dir_ in os.walk(target_dir): for f in dir_[2]: exts = f.split(".") key = exts[-1] if len(exts) != 1 else DEFAULT_KEY ext_files[key].append(os.path.join(dir_[0], f)) for ext, file_list in ext_files.items(): dest_dir = os.path.join(tmp_dir, ext) if not os.path.exists(dest_dir): os.makedirs(dest_dir) for file_path in file_list: filename = unique_covert(os.path.relpath(file_path, target_dir)) dest = os.path.join(dest_dir, filename) rel_file_path = os.path.relpath(file_path, target_dir) shutil.move(file_path, dest) yield (os.path.join(ext, filename), rel_file_path) yield None # 按修改時間分類 def classify_by_mtime(target_dir, tmp_dir): for dir_ in os.walk(target_dir): base_dir = dir_[0] for f in dir_[2]: abs_file_path = os.path.join(base_dir, f) rel_file_path = os.path.relpath(abs_file_path, target_dir) if os.path.islink(abs_file_path): rel_dest_dir = "link" dest_dir = os.path.join(tmp_dir, "link") else: mtime = os.stat(abs_file_path)[8] (y, m, d) = map(str, time.localtime(mtime)[:3]) rel_dest_dir = os.path.join(y, m, d) dest_dir = os.path.join(tmp_dir, rel_dest_dir) if not os.path.exists(dest_dir): os.makedirs(dest_dir) filename = unique_covert(rel_file_path) dest_file = os.path.join(dest_dir, filename) shutil.move(abs_file_path, dest_file) yield (os.path.join(rel_dest_dir, filename), rel_file_path) yield None # 按字母分類 def classify_by_first_letter(target_dir, tmp_dir): for dir_ in os.walk(target_dir): base_dir = dir_[0] for f in dir_[2]: abs_file_path = os.path.join(base_dir, f) rel_file_path = os.path.relpath(abs_file_path, target_dir) first_char = f[0] if first_char.isalnum(): dest_dir = os.path.join(tmp_dir, first_char) if not os.path.exists(dest_dir): os.makedirs(dest_dir) filename = unique_covert(rel_file_path) dest_file = os.path.join(dest_dir, filename) shutil.move(abs_file_path, dest_file) yield (os.path.join(first_char, filename), rel_file_path) else: shutil.move(abs_file_path, os.path.join(tmp_dir, f)) yield (f, rel_file_path) yield None def go_back(target_dir): target_dir = target_dir.decode("utf-8") tmp_dir = os.path.join(os.path.dirname(os.path.dirname(target_dir)), str(uuid4())) os.mkdir(tmp_dir) back_up_tree = {} back_up_file = os.path.join(target_dir, BACKUP_FILE) if not os.path.exists(back_up_file): raise Exception("已經是初始狀態") with open(back_up_file, "rb") as buf: back_up_tree = json.load(buf) if not back_up_tree: raise Exception("備份文件已損壞或不存在") for src, old in back_up_tree.items(): src_file = os.path.join(target_dir, src) dest_file = os.path.join(tmp_dir, old) dest_dir = os.path.dirname(dest_file) if not os.path.exists(dest_dir): os.makedirs(dest_dir) shutil.move(src_file, dest_file) shutil.rmtree(target_dir, ignore_errors=False) os.rename(tmp_dir, target_dir)def run(target_dir, classify_func): tmp_dir = os.path.join(os.path.dirname(os.path.dirname(target_dir)), str(uuid4())) os.mkdir(tmp_dir) save_backup_gen = save_back_up(target_dir) classify_gen = classify_func(target_dir, tmp_dir) finished = 0 begin = time.time() while True: tup = classify_gen.send(None) finished += 1 sys.stdout.write(u"已完成%s個文件
" % finished) sys.stdout.flush() if not tup: break save_backup_gen.send(tup) print(u"已完成%s個文件,耗時%s秒" % (finished, time.time() - begin)) shutil.rmtree(target_dir, ignore_errors=False) os.rename(tmp_dir, target_dir) try: save_backup_gen.send(None) except StopIteration: pass def _main(): parser = argparse.ArgumentParser(description="對目錄進行文件整理歸類.") parser.add_argument("directory", type=str, help="目標目錄路徑") parser.add_argument("-t", "--type", type=str, default="ext", choices=["ext", "mtime", "word", "back"], help="分類方式") args = parser.parse_args() target_dir = args.directory op = args.type if op == "ext": run(target_dir, classify_by_ext) elif op == "mtime": run(target_dir, classify_by_mtime) elif op == "word": run(target_dir, classify_by_first_letter) elif op == "back": go_back(target_dir) print ("恢復完成") else: raise Exception("參數錯誤")if __name__ == "__main__": _main()

02. 12306餘票查詢工具

前言

利用12306提供的相關介面對12306的余票信息進行查詢。

用法

usage: left_ticket.py [-h] [-f FROM_CITY] [-t TO_CITY] [-d DATE] [-s] [-l]查詢12306車次余票.optional arguments: -h, --help show this help message and exit -f FROM_CITY, --from_city FROM_CITY 起始城市 -t TO_CITY, --to_city TO_CITY 目標城市 -d DATE, --date DATE 日期,格式如:2016-08-14 -s, --student 學生票 -l, --list_city 查看支持城市列表

查詢車票

python left_ticket.py -f 唐家灣 -t 廣州南 -d 8-26 # 年份默認為今年

輸出

車次序號 起始站 出發站 終點站 時間 一等座 二等座6e000C761003 珠海->唐家灣->廣州南 09:48 54 2576e000C762202 珠海->唐家灣->廣州南 11:43 39 2356e000C763002 珠海->唐家灣->廣州南 13:40 43 3076e000C763802 珠海->唐家灣->廣州南 14:45 58 3296e000C764602 珠海->唐家灣->廣州南 16:43 57 3126e000C765802 珠海->唐家灣->廣州南 18:38 62 3566e000C766202 珠海->唐家灣->廣州南 19:45 55 3576e000C767602 珠海->唐家灣->廣州南 22:10 64 3896e000C767802 珠海->唐家灣->廣州南 22:33 64 384

嚮導模式

python left_ticket.py

輸出

請輸入起始城市(輸入回車為珠海):請輸入目的城市:廣州南請輸入出發日期(輸入回車為2016-08-14):是否成人票,是請按回車,不是請輸入n:正在查詢...車次序號 起始站 出發站 終點站 時間 一等座 二等座6e000C768602 珠海->珠海->廣州南 23:28 62 無6e000C768802 珠海->珠海->廣州南 23:58 112 33

查看支持城市

python left_ticket.py -l

輸出

阜南 祁縣東 黑水 涪陵 哈密 大灰廠 新余北 平安 欽州東 安陸 黎塘 高各庄 谷城 彭水 沙縣 海安縣 棗莊西 崑山南 克東 圖強 大苴 恩施 水富 沂南 姚千戶屯 冷水江東 ...

源碼

#!/usr/bin/python #-*- coding:utf-8 -*- import argparseimport osimport jsonimport urllib2import sslimport sysimport reimport socketfrom datetime import datetimePURPOSE_CODES = ["ADULT", "0X00"] # 成人票,學生票CITY_CACHE = NoneCITY_CACHE_FILE = ".cities"ADDR_CACHE_FILE = ".addr"CITY_LIST_URL = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js"ACTION_URL = "https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={train_time}&leftTicketDTO.from_station={from_city}&leftTicketDTO.to_station={to_city}&purpose_codes={ticket_type}"SSL_CTX = ssl.SSLContext(ssl.PROTOCOL_TLSv1)# 對月份進行補零 def add_zero(month): if int(month) < 10: month = "0" + str(int(month)) return month# 默認為今天 def default_date(): now = datetime.now() return "-".join([str(now.year), str(add_zero(now.month)), str(add_zero(now.day))])# 格式化輸入日期 # 如: # 8-14 -> 2016-08-14 # 2016:8:14 -> 2016-08-14 # -> 2016-08-14 def date_format(input_date): if not input_date: return default_date() res = re.match(r"(([0-9]{4})[-|\|:])?([0-9]{1,2})[-|\|:]([0-9]{2})", input_date) if res: year = res.group(2) month = res.group(3) day = res.group(4) now = datetime.now() if not year: year = now.year if not month: month = now.month if not day: day = now.day return "-".join([str(year), add_zero(str(month)), str(day)]) else: print ("輸入日期格式錯誤") sys.exit(-1)# 載入城市信息 def load_cities(): global CITY_CACHE if CITY_CACHE is not None: return CITY_CACHE cache_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), CITY_CACHE_FILE) need_reload = True cities = {} if os.path.exists(cache_file): with open(cache_file, "rb") as fp: cities = json.load(fp) if cities: need_reload = False if need_reload is True: city_info = urllib2.urlopen(CITY_LIST_URL, context=SSL_CTX).read() for res in re.finditer(r"@[a-z]{3}|(.+?)|([A-Z]{3})|[a-z]+?|[a-z]+?|", city_info): city = res.group(1) code = res.group(2) cities[city] = code with open(cache_file, "w") as fp: json.dump(cities, fp) CITY_CACHE = cities return cities# 查詢操作 def search(from_city, to_city, train_time, ticket_type="ADULT"): cities = load_cities() try: from_code = cities[from_city.decode("utf-8")] except KeyError: print("指定起始站點%s不存在" % from_city) sys.exit(-1) try: to_code = cities[to_city.decode("utf-8")] except KeyError: print("指定目標站點%s不存在" % to_city) sys.exit(-1) url = ACTION_URL.format(from_city=from_code, to_city=to_code, train_time=train_time, ticket_type=ticket_type) print(url) ret = json.loads(urllib2.urlopen(url, context=SSL_CTX, timeout=10).read()) if not ret or ret == -1 or not ret["data"] or len(ret["data"]) == 0: print("沒查詢到相關的車次信息") sys.exit(-1) print ("車次序號 起始站 出發站 終點站 時間 一等座 二等座") for r in ret["data"]: r = r["queryLeftNewDTO"] if (not r["zy_num"].encode("utf-8").isdigit() and not r["ze_num"].encode("utf-8").isdigit() or r["from_station_name"].encode("utf-8") != from_city): continue print (u"%s %s->%s->%s %s %s %s" %( r["train_no"], r["start_station_name"], r["from_station_name"], r["to_station_name"], r["arrive_time"], r["zy_num"], r["ze_num"] ))# 獲取ip def getip(): url = "http://jsonip.com" res = re.search("d+.d+.d+.d+", urllib2.urlopen(url, timeout=5).read()) if res: return res.group(0) return None # 根據ip獲取地址 def getaddr(fresh=False): addr_cache_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), ADDR_CACHE_FILE) if not fresh and os.path.exists(addr_cache_file): addr = None with open(addr_cache_file, "rb") as fp: addr = fp.read() if addr: return addr ip = getip() if not ip: return None addr_info = urllib2.urlopen("http://ip.taobao.com/service/getIpInfo.php?ip=%s" % ip, timeout=5).read() city = None if addr_info: addr_info = json.loads(addr_info) city = addr_info["data"]["city"] city = city.encode("utf-8").replace("市", "") with open(addr_cache_file, "w") as fp: fp.write(city) return citydef get_yn_input(msg): while True: res = raw_input("%s,是請按回車,不是請輸入n:" % msg) if res in ("", "n"): break return True if res == None else False # 默認模式 def guide(): try: cities = load_cities() city = getaddr() except socket.timeout: print ("請求超時") sys.exit(-1) if city and cities.has_key(city.decode("utf-8")): from_city = raw_input("請輸入起始站點(輸入回車為%s):" % city) if not from_city: from_city = city else: from_city = raw_input("請輸入起始站點:") while True: to_city = raw_input("請輸入目的站點:") if to_city: break dd = default_date() train_time = raw_input("請輸入出發日期(輸入回車為%s):" % dd) train_time = date_format(train_time) if train_time else dd ticket_type = "0X00" if get_yn_input("是否成人票") else "ADULT" print("正在查詢...
") search(from_city, to_city, train_time, ticket_type)if __name__ == "__main__": parser = argparse.ArgumentParser(description="查詢12306車次余票.") parser.add_argument("-f", "--from_city", type=str, help="起始城市") parser.add_argument("-t", "--to_city", type=str, help="目標城市") parser.add_argument("-d", "--date", type=str, help="日期,格式如:2016-08-14") parser.add_argument("-s", "--student", action="store_true", help="學生票") parser.add_argument("-l", "--list_city", action="store_true", help="查看支持城市列表") args = parser.parse_args() from_city = args.from_city to_city = args.to_city train_time = date_format(args.date) ticket_type = PURPOSE_CODES[1] if args.student is True else PURPOSE_CODES[0] list_city = args.list_city if from_city is None and to_city is None and list_city is False: guide() else: if list_city: for city, code in load_cities().items(): print city, elif from_city and to_city and ticket_type: search(from_city, to_city, train_time, ticket_type) else: print ("參數錯誤")

03. 文本備份雲倉庫

前言

everbox是一個將evernote作為文件沙盒的介面集合,利用evernote作為文本的存儲倉庫,方便地對文本文件進行管理。

用法

usage: everbox.py [-h] {init,push,pushall,list,drop,drag,remove,pull,log} ...文本備份助手.optional arguments: -h, --help show this help message and exit操作命令: {init,push,pushall,list,drop,drag,remove,pull,log} init 新建一個倉庫 push 添加文本到倉庫 pushall 添加批量文本到倉庫 list 列出倉庫或文本 drop 刪除一個倉庫 drag 從遠程拉取一個文件同時刪除記錄 remove 從倉庫刪除指定id的文本 pull 從倉庫拉取文本 log 查看文本記錄信息

準備工作

安裝evernote sdk for python

pip install evernote

登錄Evernote開發者,獲取開發Token,把獲取到的token替換掉代碼中的dev_token。

基本操作

init 新建一個倉庫

usage: everbox.py init [-h] box新建一個倉庫positional arguments: box 倉庫名字python everbox.py init test創建成功,id為:0c6e25c4-538c-4008-87e2-7efe32e18280

list 列出倉庫或文本

usage: everbox.py list [-h] [box]列出倉庫文本positional arguments: box 倉庫id或倉庫名字

獲取所有倉庫

python everbox.py list| 文本id | 倉庫名稱 |6da27e72-ad2d-4cd0-a05a-f1fc12d9e44c 我的第一個筆記本1902a691-62f3-4edc-a8bb-4db6d949da50 示例筆記本

獲取倉庫文本

python everbox.py list 6da2| 文本id | 文本名稱 |b00204f8-41d0-43bb-8fc3-17b3a654360f README.mdf7c7b2be-c247-4c2a-8001-186d27942cce README.md

pushall 推送所有文本

usage: everbox.py pushall [-h] [-b BOX] [files [files ...]]添加批量文本到倉庫positional arguments: files 文本路徑,多個以空格間隔optional arguments: -h, --help show this help message and exit -b BOX, --box BOX 倉庫id或倉庫名字python everbox.py pushall -b 6da2 README.md已上傳(1/1)個文本python everbox.py pushall README.md無指定倉庫,將使用默認倉庫已上傳(1/1)個文本

log 查看文件在倉庫中的記錄

usage: everbox.py log [-h] file查看文本記錄信息positional arguments: file 文本名稱python everbox.py log README.md

輸出

| 文本id | 文本名稱 | 倉庫 | 創建時間b00204f8-41d0-43bb-8fc3-17b3a654360f README.md 我的第一個筆記本 2016-08-16 17:14:07f7c7b2be-c247-4c2a-8001-186d27942cce README.md 我的第一個筆記本 2016-08-16 17:15:02

pull 從倉庫中拉取文件

usage: everbox.py pull [-h] [-b BOX] [-y] [files [files ...]] directory從倉庫拉取文本positional arguments: files 文本guid或名稱(若用名稱則取最新的同名 ),多個以空格間隔 directory 拉取目錄optional arguments: -h, --help show this help message and exit -b BOX, --box BOX 倉庫id或倉庫名字 -y, --yes 忽略覆蓋提示python everbox.py pull b00204f8-41d0-43bb-8fc3-17b3a654360f .

輸出

文件 /Users/tonnie/github/one-week/03-everbox/README.md 已存在,是否覆蓋,是請按y,不是請輸入n:y成功拉取:1個文件

remove 從倉庫刪除指定的文本

usage: everbox.py remove [-h] guid從倉庫刪除指定id的文本positional arguments: guid 文本guidpython everbox.py remove d8bc4812-bfc2-44cd-9aee-bc7a92887e70

輸出

刪除成功

drag 從遠程拉取一個文件同時刪除記錄

usage: everbox.py drag [-h] guid directory從遠程拉取一個文本同時刪除記錄positional arguments: guid 文本guid directory 拉取目錄python everbox.py drag f7c7b2be-c247-4c2a-8001-186d27942cce ~

輸出

拉取完成刪除成功

drop 刪除一個倉庫

usage: everbox.py drop [-h] box刪除一個倉庫positional arguments: box 倉庫id或倉庫名字python everbox.py drop 我的第一個筆記本

輸出

刪除成功

源碼

#!usr/bin/python #-*- coding:utf-8 -*- import argparseimport binasciiimport hashlibimport osimport sysimport base64from datetime import datetime, datetry: import evernote from evernote.api.client import EvernoteClient import evernote.edam.type.ttypes as Types import evernote.edam.notestore.ttypes as NoteTypesexcept: print ("未安裝evernote的擴展,請安裝後重試") sys.exit(-1)try: import socket s = socket.create_connection(("sandbox.evernote.com", 80), 5)except Exception,e: print("無法連接到evernote,請檢查網路連接") sys.exit(-1)dev_token = "S=s1:U=92d14:E=15de8ebccac:C=156913a9da8:P=1cd:A=en-devtoken:V=2:H=ca0bbceb23208c3cde8227aa5912761a" from contextlib import contextmanager_loading = True def loading(hint): while _loading: sys.stdout.write(hint + "
") sys.stdout.flush()# 耗時操作的提示 @contextmanager def open_loading(hint): from threading import Thread global _loading _loading = True t = Thread(target=loading, args=[hint]) t.start() yield _loading = False class LazyGet: def __init__(self, construct_func, hint=None, end_hint=None, excp_hint=None): self._func = construct_func self._ins = None self._hint = hint self._end_hint = end_hint self._excp_hint = excp_hint def __call__(self): if self._ins is not None: return self._ins print (self._hint) try: self._ins = self._func() except Exception, e: print (self._excp_hint) sys.exit(-1) print (self._end_hint) return self._insget_client = LazyGet(lambda : EvernoteClient(token=dev_token), "初始化組件...", "初始化成功", "初始化失敗")get_box_store = LazyGet(lambda : get_client().get_note_store(), "連接evernote...", "連接成功", "連接失敗")get_boxes = LazyGet(lambda : get_box_store().listNotebooks(), "獲取倉庫信息...", "獲取倉庫成功", "獲取失敗")def create_box(name): box = Types.Notebook() box.name = name return boxdef create_file(title, content, box_id="", image_resource=None): hash_hex = "" file = Types.Note() if box_id: file.notebookGuid = box_id if image_resource: (resource, image_hash) = image_resource file.resources = [resource] hash_hex = binascii.hexlify(image_hash) file.title = title file.content = """<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"> <en-note><caption>%s</caption>""" % content if hash_hex: file.content += "<en-media type="image/png" hash="%s"/>" % hash_hex file.content += "</en-note>" return filedef parse_file(content): file_content = "" try: content = content.split("<caption>")[1].split("</caption>")[0] except: pass media_index = content.find("<en-media") content = content[:media_index] file_lst = content.split("<br/>") for content in file_lst: file_content += content return file_contentdef load_file(guid): file = None try: file = get_box_store().getNote(dev_token, guid, True, True, False, False) except Exception, e: return None file_content = parse_file(file.content) return { "title": file.title, "content": base64.b64decode(file_content + "=" * (-len(file_content) % 4)), "created": date.fromtimestamp(file.created / 100).strftime("%d/%m/%Y") }def get_box_by_id(box_id): if len(box_id) < 4: print ("id匹配長度至少為4") sys.exit(-1) for box in get_boxes(): if box.guid.startswith(box_id): return box return "" def get_box_by_name(name): for box in get_boxes(): if box.name == name: return box return "" def get_box(id_or_name): if not id_or_name: return "" box = get_box_by_id(args.box) if not box: box = get_box_by_name(args.box) if not box: print ("指定倉庫不存在") sys.exit(-1) return boxdef push_to_box(note): note = get_box_store().createNote(dev_token, note) return notedef get_yn_input(msg): while True: res = raw_input("%s,是請按y,不是請輸入n:" % msg) if res in ("y", "n"): break return True if res == "y" else False def get_abs_dir(directory): dest_dir = directory or os.path.abspath(".") if not os.path.exists(dest_dir) or not os.path.isdir(dest_dir): print ("指定目錄不存在") sys.exit(-1) dest_dir = os.path.abspath(os.path.normpath(os.path.expanduser(dest_dir))) return dest_dirdef datetime_format(time): return datetime.fromtimestamp(int(str(time)[:-3])).strftime("%Y-%m-%d %H:%M:%S")def init(args): boxname = args.box box = create_box(boxname) try: box = get_box_store().createNotebook(dev_token, box) if not box: raise print ("創建成功,id為:%s" % box.guid) except Exception,e: print ("創建失敗")def pull(args): dest_dir = get_abs_dir(args.directory) skip_cover = args.yes finished = 0 for f in args.files: try: flag = os.path.basename(f) file = load_file(flag) if not file: box = get_box(args.box) file_filter = NoteTypes.NoteFilter() if box: file_filter.notebookGuid = box.guid file_filter.title = flag files = get_box_store().findNotes(dev_token, file_filter, 0, 100).notes file = load_file(files[-1].guid) if not file: raise ouput_file = os.path.join(dest_dir, file["title"]) if os.path.exists(ouput_file): if not skip_cover: if not get_yn_input("文件 %s 已存在,是否覆蓋" % ouput_file): continue with open(ouput_file, "w") as fp: fp.write(file["content"]) finished += 1 sys.stdout.write("已拉取:%s個文件
" % finished) sys.stdout.flush() except Exception, e: print ("文件:%s拉取失敗,跳過.." % f) print("成功拉取:%s個文件" % finished)def list(args): def list_box(box): file_filter = NoteTypes.NoteFilter() file_filter.notebookGuid = box.guid files = get_box_store().findNotes(dev_token, file_filter, 0, 100).notes if not files: print "倉庫沒有任何文本" else: print ("| 文本id | 文本名稱 | 創建時間") for f in reversed(files): print "%s %s %s" %(f.guid, f.title, datetime_format(f.created)) # 沒有指定倉庫,則列出所有倉庫 if args.box is None: boxes = get_boxes() print ("| 倉庫id | 倉庫名稱 | 創建時間") for box in boxes: print box.guid, box.name, datetime_format(box.serviceCreated) else: box = get_box(args.box) list_box(box)def push(args): box = get_box(args.box) abs_path = os.path.abspath(os.path.normpath(args.file)) if not os.path.exists(abs_path): print ("文本路徑不存在") return try: with open(abs_path, "rb") as fp: title = os.path.basename(abs_path) if args.box: box = get_box(args.box) file = create_file(title, fp.read(), box.guid, "") else: print ("無指定倉庫,將使用默認倉庫") file = create_file(title, base64.b64encode(fp.read()), None, "") push_to_box(file) print ("%s 上傳成功" % abs_path) except Exception, e: print e print ("上傳%s時,發生異常" % abs_path)def pushall(args): files = args.files to_add = [] for f in files: abs_path = os.path.abspath(os.path.normpath(f)) if not os.path.exists(abs_path): print ("%s:文本路徑不存在,跳過" % f) continue if os.path.getsize(abs_path) > 1000 * 1000 * 10: # 10M print ("%s: 文本體積大於10M,跳過" % f) continue to_add.append(os.path.abspath(os.path.normpath(f))) else: total = len(to_add) finished = 0 for f in to_add: try: with open(f, "rb") as fp: title = os.path.basename(f) if args.box: box = get_box(args.box) file = create_file(title, fp.read(), box.guid, "") else: print ("無指定倉庫,將使用默認倉庫") file = create_file(title, fp.read(), None, "") push_to_box(file) finished += 1 sys.stdout.write("已上傳(%s/%s)個文本
" % (finished, total)) sys.stdout.flush() except Exception, e: print ("上傳%s時,發生異常" % f) print("已上傳(%s/%s)個文本" % (finished, total))def remove(args): guid = args.guid try: get_box_store().deleteNote(dev_token, guid) print ("刪除成功") except: print ("刪除失敗")def drop(args): box = get_box(args.box) try: get_box_store().expungeNotebook(dev_token, box.guid) print ("刪除成功") except: print ("刪除失敗")def drag(args): dest_dir = get_abs_dir(args.directory) file = load_file(args.guid) if not file: print ("文件拉取失敗") output_file = os.path.join(os.path.join(dest_dir, file["title"])); if os.path.exists(output_file): if not get_yn_input("文件 %s 已存在,是否覆蓋" % output_file): return with open(output_file, "w") as fp: fp.write(file["content"]) print ("拉取完成") remove(args)def log(args): file = args.file abs_path = os.path.abspath(os.path.normpath(file)) if not os.path.exists(abs_path): print ("文件不存在!") return file_name = os.path.basename(abs_path) file_filter = NoteTypes.NoteFilter() file_filter.title = file_name files = get_box_store().findNotes(dev_token, file_filter, 0, 100).notes if not files: print ("倉庫中不存在該文件的記錄") return print ("| 文本id | 文本名稱 | 倉庫 | 創建時間") for f in files: print "%s %s %s %s" %(f.guid, f.title, get_box_by_id(f.notebookGuid).name, datetime_format(f.created))if __name__ == "__main__": parser = argparse.ArgumentParser(description="文本備份助手.") subparsers = parser.add_subparsers(title="操作命令") init_cmd = subparsers.add_parser("init", help="新建一個倉庫", description="新建一個倉庫") init_cmd.add_argument("box", help="倉庫名字") init_cmd.set_defaults(func=init) push_cmd = subparsers.add_parser("push", help="添加文本到倉庫", description="添加文本到倉庫") push_cmd.add_argument("-b", "--box", help="倉庫id或倉庫名字") push_cmd.add_argument("file") push_cmd.set_defaults(func=push) push_all_cmd = subparsers.add_parser("pushall", help="添加批量文本到倉庫", description="添加批量文本到倉庫") push_all_cmd.add_argument("-b", "--box", help="倉庫id或倉庫名字") push_all_cmd.add_argument("files", nargs="*", help="文本路徑,多個以空格間隔") push_all_cmd.set_defaults(func=pushall) list_cmd = subparsers.add_parser("list", help="列出倉庫或文本", description="列出倉庫或文本") list_cmd.add_argument("box", nargs="?", help="倉庫id或倉庫名字") list_cmd.set_defaults(func=list) drop_cmd = subparsers.add_parser("drop", help="刪除一個倉庫", description="刪除一個倉庫") drop_cmd.add_argument("box", help="倉庫id或倉庫名字") drop_cmd.set_defaults(func=drop) drag_cmd = subparsers.add_parser("drag", help="從遠程拉取一個文件同時刪除記錄", description="從遠程拉取一個文件同時刪除記錄") drag_cmd.add_argument("guid", help="文本guid") drag_cmd.add_argument("directory", type=str, help="拉取目錄") drag_cmd.set_defaults(func=drag) remove_cmd = subparsers.add_parser("remove", help="從倉庫刪除指定id的文本", description="從倉庫刪除指定id的文本") remove_cmd.add_argument("guid", help="文本guid") remove_cmd.set_defaults(func=remove) pull_cmd = subparsers.add_parser("pull", help="從倉庫拉取文本", description="從倉庫拉取文本") pull_cmd.add_argument("-b", "--box", help="倉庫id或倉庫名字") pull_cmd.add_argument("-y", "--yes", action="store_true", help="忽略覆蓋提示") pull_cmd.add_argument("files", nargs="*", help="文本guid或名稱(若用名稱則取最新的同名),多個以空格間隔") pull_cmd.add_argument("directory", type=str, help="拉取目錄") pull_cmd.set_defaults(func=pull) log_cmd = subparsers.add_parser("log", help="查看文本記錄信息", description="查看文本記錄信息") log_cmd.add_argument("file", help="文本名稱") log_cmd.set_defaults(func=log) args = parser.parse_args() args.func(args)

04. ascii圖形預覽

前言

把圖像轉為ascii字元。

用法

python ascii-image.py [圖像路徑]

輸出

源碼

#-*- coding:utf-8 -*- from PIL import Imageimport sysimport os# 加上顏色 class BColor: HEADER = "33[95m" OKBLUE = "33[94m" OKGREEN = "33[92m" WARNING = "33[93m" FAIL = "33[91m" ENDC = "33[0m" BOLD = "33[1m" UNDERLINE = "33[4m" def _main(): try: pic = os.path.abspath(sys.argv[1]) except: print("指定圖片路徑") img = Image.open(pic) width = int(img.size[0]) height = int(img.size[1]) gray_img = img.convert("L") scale = width // 100 char_lst = " .:-=+*#%@" char_len = len(char_lst) arr = [] for y in range(0, height, scale): for x in range(0, width, scale): brightness = 0 r = g = b = 0 count = 0 for ix in range(scale): for iy in range(scale): if (x + ix) == width or (y + iy) == height: break count += 1 b = 255 - gray_img.getpixel((x+ix, y+iy)) brightness += b choice = int(char_len * (brightness // count / 255) ** 1.2) if choice >= char_len: choice = char_len sys.stdout.write(char_lst[choice]) sys.stdout.write("
") sys.stdout.flush()if __name__ == "__main__": _main()

05. html生成器

前言

用python生成html

用法

from htmlgen import hh("html") # <html></html>

更深入的例子

datas = [ ["1 + 1", 2], ["1 + 2", 3], ["2 + 2", 4]]

參數語法

build(h("html", c=[ h("head", c=[ h("title", "My Title"), h("meta", charset="utf-8"), hc("This is comment"), hcss("test.css") ]), h("body#main.class1 class2", c=[ h("h1", "HtmlGen") * 2, h("ul", extra=1, c=[ hmap("li", "I am {?}!", [1,2,3,4,5]) ]), h("ul", c=[ hfor(5, lambda i: h("li", "{}").format(chr(ord(str(i)) + 17))) ]), h("table", c=[ h("tr", c=[ h("td"), heach(dict(name="result"), lambda k, v: h("td", v)) ]), heach(datas, lambda v: h("tr", c=[ heach(v, lambda v: h("td", v, stylex="border:1px solid black;")), ]) ) ]), ~ hjs("test.js") ]), ]), "test.html")

注入語法

build(h("html") <= [ h("head") <= [ h("title", "My Title"), h("meta", charset="utf-8"), hc("This is comment"), hcss("test.css") ], h("body#main.class1 class2") <= [ h("h1", "HtmlGen") * 2, h("ul", extra=1) <= [ hmap("li", "I am {?}!", [1,2,3,4,5]) ], h("ul") <= [ hfor(5, lambda i: h("li", "{}").format(chr(ord(str(i)) + 17))) ], h("table") <= [ h("tr") <= [ h("td"), heach({"name": "result"}, lambda k, v: h("td", v)) ], heach(datas, lambda v: h("tr") <= [ heach(v, lambda v: h("td", v, stylex="border:1px solid black;")), ] ) ], ~ hjs("test.js") # comment,too ], ], "test.html")

以上代碼會生成如下html:

<html><head> <title>My Title</title> <meta charset="utf-8"></meta> <!-- This is comment --> <link rel="stylesheet" type="text/css" href="test.css"></head><body id="main" class="class1 class2"> <h1>HtmlGen</h1> <h1>HtmlGen</h1> <ul extra="1"> <li>I am 1!</li> <li>I am 2!</li> <li>I am 3!</li> <li>I am 4!</li> <li>I am 5!</li> </ul> <ul> <li>A</li> <li>B</li> <li>C</li> <li>D</li> <li>E</li> </ul> <table> <tr> <td></td> <td>result</td> </tr> <tr> <td stylex="border:1px solid black;">1 + 1</td> <td stylex="border:1px solid black;">2</td> </tr> <tr> <td stylex="border:1px solid black;">1 + 2</td> <td stylex="border:1px solid black;">3</td> </tr> <tr> <td stylex="border:1px solid black;">2 + 2</td> <td stylex="border:1px solid black;">4</td> </tr> </table> <!-- <script type="text/javascript" src="test.js"></script> --></body></html>

源碼

#-*- coding:utf-8 -*- import reclass Piece(object): _html = "<{tag}{attrs}>{content}{childs}</{tag}>" def __init__(self, tag="", attrs={}, content="", childs="", raw=None): self.raw = raw self.tag = tag self.attrs = attrs self.content = content self.childs = childs def resolve(self): if self.raw: return self.raw attrs = make_attrs(self.attrs) self.html = self._html.format(tag=self.tag, attrs=attrs, content=self.content, childs=self.childs) return self.html def format(self, *args, **kws): return self.resolve().format(*args, **kws) def __str__(self): return self.resolve() def __invert__(self): return "<!-- {} -->".format(self.resolve()) # child"s inject def __le__(self, childs): self.childs = "".join([str(o) for o in childs]) return self def __mul__(self, num): return str(self) * 2 def __getattr__(self, attr): return self.attrs.get(attr, None) __repr__ = __str__def make_attrs(attrs): attrs = "" + " ".join(["{}="{}"".format(k, v) for k, v in attrs.items()]) attrs = " {}".format(attrs) if attrs else "" return attrstag_flg = re.compile(r"(?P<tag>[w]+)(#(?P<id>[w]+))?(.(?P<class>[ws]+))?")def h(tag, content="", **attrs): if tag: m = re.match(tag_flg, tag) if m: groups = m.groupdict() if groups["id"] is not None: attrs["id"] = groups["id"] if groups["class"] is not None: attrs["class"] = groups["class"] if groups["tag"] is not None: tag = groups["tag"] childs = attrs.pop("c", []) child_html = "".join([str(c) for c in childs]) return Piece(tag, attrs, content, child_html)def hmap(tag, content="", datas=None, **attrs): if datas is None: datas = [] htmls = [] for data in datas: html = Piece._html.format( tag=tag, attrs=make_attrs(attrs), content=content.replace("{?}", str(data)), childs="" ) htmls.append(html) return "".join(htmls)def hcss(path): return Piece(raw="<link rel="stylesheet" type="text/css" href="{}">".format(path))def hjs(path): return Piece(raw="<script type="text/javascript" src="{}"></script>".format(path))def hc(comment): return "<!-- {} -->".format(comment)def heach(iterable, func): res = [] if isinstance(iterable, list): for value in iterable: res.append(str(func(value))) elif isinstance(iterable, dict): for key, value in iterable.items(): res.append(str(func(key, value))) return "".join(res)def hfor(times, func, **injects): res = [] for i in range(times): res.append(func(i)) return "".join(res)def _main(): def build(piece, path): buf = piece.resolve() with open(path, "w") as fp: fp.write(buf) datas = [ ["1 + 1", 2], ["1 + 2", 3], ["2 + 2", 4] ] build(h("html") <= [ h("head") <= [ h("title", "My Title"), h("meta", charset="utf-8"), hc("This is comment"), hcss("test.css") ], h("body#main.class1 class2") <= [ h("h1", "HtmlGen") * 2, h("ul", extra=1) <= [ hmap("li", "I am {?}!", [1,2,3,4,5]) ], h("ul") <= [ hfor(5, lambda i: h("li", "{}").format(chr(ord(str(i)) + 17))) ], h("table") <= [ h("tr") <= [ h("td"), heach({"name": "result"}, lambda k, v: h("td", v)) ], heach(datas, lambda v: h("tr") <= [ heach(v, lambda v: h("td", v, stylex="border:1px solid black;")), ] ) ], ~ hjs("test.js") # comment,too ], ], "test.html")if __name__ == "__main__": _main()

06. web微型框架

前言

python web微型框架

實現功能:

  • 解析請求和產生響應(基於WebOb)
  • 路由解析(基於正則匹配)
  • 模版渲染(基於jinja2)

用法

from pyboa import PyBoa, render_templateimport timeapp = PyBoa()@app.route("/", methods=["GET", "POST"]) def index(req): # 獲取請求方法 print("req.method: {}".format(req.method)) # 獲取請求參數 print("req.params: {}".format(req.params)) # 獲取GET參數 print("req.GET: {}".format(req.GET)) # 獲取POST參數 print("req.POST: {}".format(req.POST)) # 獲取Environ參數 print("req.environ: {}".format(req.environ)) return render_template("index.html", time=time.time())@app.route("/page") def page(req): return "page" # 這條語句會導致循環導入 # app.add_route("/page/{year:dddd}", controller="test:page")app.add_route("/page/{year:dddd}", controller=page)if __name__ == "__main__": app.run()

源碼

from jinja2 import Environment, FileSystemLoaderfrom webob.request import Request as WebObRequestfrom webob.response import Response as WebObResponsefrom webob.dec import wsgifyfrom webob import excfrom wsgiref.simple_server import make_serverimport sysimport osimport re__all__ = [ "PyBoa", "make_response", "render_template"]_jinja_env = Environment(loader=FileSystemLoader(os.path.abspath("./templates")))# 匹配路由的正則表達式rule_regex = re.compile(r""" { (w+) (?::([^}]+))? } """, re.VERBOSE)def _is_immutable(self): raise TypeError("%r objects are immutable" % self.__class__.__name__)iteritems = lambda d, *args, **kwargs: iter(d.items(*args, **kwargs))class ImmutableDictMixin(object): _hash_cache = None def __setitem__(self, key, value): _is_immutable(self) def __delitem__(self, key): _is_immutable(self) def clear(self): _is_immutable(self) def pop(self): _is_immutable(self) def update(self): _is_immutable(self) def setdefault(self): _is_immutable(self) def _iter_hashitems(self): return iteritems(self) def __hash__(self): if self._hash_cache is not None: return self._hash_cache rv = self._hash_cache = hash(frozenset(self._iter_hashitems())) return rvclass ImmutableDict(ImmutableDictMixin, dict): def __repr__(self): return "%s(%s)" % ( self.__class__.__name__, dict.__repr__(self), ) def copy(self): return dict(self) def __copy__(self): return selfclass Request(WebObRequest): pass class Response(WebObResponse): content_type = "text/html"wsgify.RequestClass = Requestdef make_response(**options): resp = Response(**options) return respdef render_template(template_name, **context): return _jinja_env.get_template(template_name).render(context)def load_controller(string): module_name, func_name = string.split(":", 1) if module_name: __import__(module_name) else: file_path = sys._getframe(2).f_code.co_filename.replace(".py", "") module_name = os.path.basename(file_path) __import__(module_name) module = sys.modules[module_name] func = getattr(module, func_name) func = wsgify(func) return funcclass Config(dict): def from_object(self, obj): for key in dir(obj): # 檢查所有字母是否均為大寫,是則視為配置參數 if key.isupper(): self[key] = objclass PyBoa(object): default_config = ImmutableDict({ "DEBUG": True, }) def __init__(self): self.routes = [] self.config = Config(self.default_config) def add_route(self, template, controller, **options): if isinstance(controller, str): controller = load_controller(controller) options.setdefault("methods", ("GET", )) self.routes.append((re.compile(rule_to_regex(template)), controller, options)) def __call__(self, environ, start_response): req = Request(environ) for regex, controller, options in self.routes: match = regex.match(req.path_info) if match: if req.method not in options["methods"]: # methods參數 return exc.HTTPMethodNotAllowed()(environ, start_response) req.urlvars = match.groupdict() req.urlvars.update(options) return controller(environ, start_response) return exc.HTTPNotFound()(environ, start_response) def route(self, rule, **options): def decorator(view): view = wsgify(view) self.add_route(rule, controller=view, **options) return view return decorator def run(self, host="127.0.0.1", port=8000, **options): server = make_server(host, port, self) print("Serving on port {}...".format(port)) try: server.serve_forever() except: server.shutdown()def rule_to_regex(rule): regex = "" last_pos = 0 for match in rule_regex.finditer(rule): regex += re.escape(rule[last_pos:match.start()]) var_name = match.group(1) expr = match.group(2) or "[^/]+" expr = "(?P<%s>%s)" % (var_name, expr) regex += expr last_pos = match.end() regex += re.escape(rule[last_pos:]) regex = "^%s$" % regex return regex

07. 城市信息服務

前言

利用高德地圖api查詢城市信息

用法

獲取高德地圖API_KEY

API_KEY = "YOUR_API_KEY"usage: city.py [-h] [-k KEYWORD] {info,place,bus} ...城市信息查詢.optional arguments: -h, --help show this help message and exit -k KEYWORD, --keyword KEYWORD 關鍵詞操作命令: {info,place,bus} info 查詢城市簡介 place 查詢城市信息 bus 查詢公交信息

查詢城市簡介

usage: city.py info [-h] [city]查詢城市簡介positional arguments: city 查詢城市(默認為ip所在城市)python city.py info 珠海

輸出

珠海,珠江口西岸的核心城市,經濟特區,珠江三角洲南端的一個重要城市,位於廣東省珠江口的西南部,區位優越,東與香港隔海相望,南與澳門相連,西鄰新會、台山市,北與中山市接壤。設有拱北、九洲、珠海港、萬山、橫琴、斗門、灣仔、珠澳跨境工業區等8個國家一類口岸,是珠三角中海洋面積最大、島嶼最多、海岸線最長的城市,素有「百島之市」之稱。珠海生態環境優美,山水相間,陸島相望,氣候宜人,是全國唯一以整體城市景觀入選「全國旅遊勝地四十佳」的城市。人居環境一流。珠海是中國最早實行對外開放政策的四個經濟特區之一,陸地面積有1701平方千米,戶籍人口106.01萬(2011年末),是廣東省人口規模最小的地級市。2013中國城市可持續發展指數報告珠海綜合排名全國第一,珠海為中國新興城市50強,新型花園城市;珠海屬國家新頒布的「幸福之城」,有「浪漫之城」的稱號。

查詢城市信息

usage: city.py place [-h] keyword [city]查詢城市信息positional arguments: keyword 查詢的關鍵詞 city 查詢城市(默認為ip所在城市)python city.py place 肯德基

輸出

+-------------------------+-------------------------------------------------------+--------------------------------------+| 名稱 | 地址 | 電話 |+-------------------------+-------------------------------------------------------+--------------------------------------+| 肯德基(人民西路店) | 人民西路仁恆星園商業街一層商鋪 | 0756-2608108 || 肯德基(三灶店) | 映月路65-67號1層 | 4008823823;0756-7511166;4009200715 || 肯德基(拱北汽車站店) | 友誼路20號1、2層 | 0756-8887871;4009200715 || 肯德基(迎賓店) | 迎賓南路1126號迎賓百貨廣場2層 | 4008823823 || 肯德基(吉大店) | 景山路220號珠海免稅商場 | 0756-3374325;13680023140 || 肯德基(明珠店) | 明珠南路1389號明珠商業廣場1層 | 0756-8629257;4009200715 || 肯德基(井岸店) | 井岸鎮新民路18-22號1層 | 0756-5559659;0756-5111163;4009200715 || 肯德基(時代廣場店) | 人民西路808號華潤萬佳1層 | 0756-2651502;4008823823 || 肯德基(鳳凰南路店) | 鳳凰南路1128號 | 0756-2115782;4009200715 || 肯德基(檸溪店) | 檸溪路284號文化廣場 | 0756-2625733;4008823823 || 肯德基(夏灣店) | 夏灣路夏灣市場1層 | 0756-8882821;0756-8884008;4009200715 || 肯德基(朝福店) | 井岸步行街新民路144號 | 0756-5111163 || 肯德基(南坑店) | 市場集團南坑商貿樓1層 | 0756-2169018;4009208801 || 肯德基(南屏路店) | 南屏鎮環屏路1號華夏國際商務酒店2層 | 0756-8911006 || 肯德基(前山店) | 前山路前山市場A圈一二層(近得一超市) | 0756-8986233 || 肯德基(九洲港店) | 情侶路599號九洲港客運大樓一層 | 0756-3262230 || 肯德基(紫荊店) | 紫荊路301號至尊寶大廈1-2層 | 0756-2127203;0756-2127662;4008823823 || 肯德基(口岸店) | 口岸廣場B1層 | 0756-8307613 || 肯德基(山場路店) | 山場路1號五洲花城1層 | 0756-2535337;4008823823;4009200715 || 肯德基(僑光店) | 拱北僑光路37號國泰酒店一層 | 0756-8889017 || 肯德基(珠海機場店kfc店) | 三灶鎮海澄機場候機大樓主樓(中指廊)二樓出發大廳SD025號 | 0756-7680932;4009200715 || 肯德基(華髮商都店) | 珠海大道8號華髮商都2號樓1層A1028、A1029號 | 0756-8921086;0756-8921085 |+-------------------------+-------------------------------------------------------+--------------------------------------+

查詢巴士信息

usage: city.py bus [-h] start end [city]查詢公交信息positional arguments: start 出發地 end 目的地 city 查詢城市python city.py bus 唐家市場 圓明新園

輸出

+-----------------------------------+----------+----------+----------+--------+--------+----------+-----------+| 路線 | 上車站 | 下車站 | 途徑站數 | 首班車 | 末班車 | 預計時間 | 步行距離 |+-----------------------------------+----------+----------+----------+--------+--------+----------+-----------+| 方案1 | | | | | | | 0.844公里 || 69路(城軌唐家灣站--圓明新園) | 唐家市場 | 圓明新園 | 28 | 06:05 | 22:20 | 48分鐘 | || | | | | | | | || 方案2 | | | | | | | 0.861公里 || K3路(城軌唐家灣站--拱北口岸總站) | 唐家市場 | 九洲城 | 6 | 06:05 | 20:50 | 29分鐘 | || ---換乘--- | | | | | | | || 25路(九洲港--屏北三路西) | 九洲城 | 圓明新園 | 5 | 06:15 | 23:10 | 20分鐘 | || 40路(吉大總站--上沖檢查站) | 九洲城 | 圓明新園 | 5 | 06:15 | 23:30 | 20分鐘 | || 60路(吉大總站--灣仔) | 九洲城 | 圓明新園 | 8 | 06:20 | 22:20 | 24分鐘 | || | | | | | | | || 方案3 | | | | | | | 0.949公里 || K1路(城軌珠海北站--拱北口岸總站) | 唐家市場 | 摩爾廣場 | 8 | 06:05 | 21:15 | 34分鐘 | || ---換乘--- | | | | | | | || 1路(城軌珠海站--香洲) | 摩爾廣場 | 圓明新園 | 1 | 06:20 | 01:15 | 15分鐘 | || 62路(橫琴口岸西--圓明新園) | 摩爾廣場 | 圓明新園 | 2 | 07:20 | 20:30 | 16分鐘 | || | | | | | | | || 方案4 | | | | | | | 0.872公里 || K3路(城軌唐家灣站--拱北口岸總站) | 唐家市場 | 吉大 | 7 | 06:05 | 20:50 | 30分鐘 | || ---換乘--- | | | | | | | || 992路(光大國貿--錦繡國際花城) | 吉大 | 圓明新園 | 3 | 06:25 | 21:00 | 18分鐘 | || | | | | | | | || 方案5 | | | | | | | 2.067公里 || K1路(城軌珠海北站--拱北口岸總站) | 唐家市場 | 隧道南 | 7 | 06:05 | 21:15 | 33分鐘 | || 10A路(城軌唐家灣站--拱北口岸總站) | 唐家市場 | 隧道南 | 18 | 06:15 | 22:05 | 38分鐘 | || 10F路(金鼎工業園北--城軌珠海站) | 唐家市場 | 隧道南 | 21 | 06:10 | 21:50 | 39分鐘 | || 10路(下柵檢查站--城軌珠海站) | 唐家市場 | 隧道南 | 21 | 06:05 | 22:00 | 39分鐘 | || ---換乘--- | | | | | | | || | | | | | | | |+-----------------------------------+----------+----------+----------+--------+--------+----------+-----------+

源碼

#-*- coding:utf-8 -*- import argparseimport urllib2import reimport jsonfrom prettytable import PrettyTableAPI_KEY = "5092e0ce602c4585e06316bfc3158ea2" def getip(): url = "http://jsonip.com" opener = urllib2.urlopen(url, timeout=5) if url == opener.geturl(): info = opener.read() res = re.search("d+.d+.d+.d+",info) if res: return res.group(0) return None # {"status":"1","info":"OK","infocode":"10000","province":"廣東省","city":"珠海市","adcode":"440400","rectangle":"113.0991626,21.9335713;113.7227333,22.39738989"} def get_geo(): ip = getip() ret = urllib2.urlopen("http://restapi.amap.com/v3/ip?ip=%s&output=json&key=%s" %(ip, API_KEY)).read() return json.loads(ret)def get_around_keyword(location, keyword): ret = urllib2.urlopen("http://restapi.amap.com/v3/place/around?key=%s&location=%s&output=json&radius=10000&keywords=%s" %(location, API_KEY, keyword)).read() return json.loads(ret)def get_city(args): city = args.city if not city: city = get_geo()["city"] if isinstance(city, unicode): city = city.encode("utf-8") return citydef get_place(keyword, city): ret = urllib2.urlopen("http://restapi.amap.com/v3/place/text?&keywords={}&city={}&output=json&offset=100&page=1&key={}&extensions=all".format(keyword, city, API_KEY)).read() if not ret: return None res = json.loads(ret) return resdef place(args): city = get_city(args) keyword = args.keyword res = get_place(keyword, city) t = PrettyTable(["名稱", "地址", "電話"]) for r in res["pois"]: t.add_row([r["name"], r["address"], r["tel"]]) print (t)def bus(args): start = args.start end = args.end city = get_city(args) res = get_place(start, city) if not res["pois"]: print ("無法找到起始位置") return start_point = res["pois"][0]["location"] res = get_place(end, city) if not res["pois"]: print ("無法找到目的位置") return end_point = res["pois"][0]["location"] ret = urllib2.urlopen("http://restapi.amap.com/v3/direction/transit/integrated?origin=%s&destination=%s&city=010&output=json&key=%s" %(start_point, end_point, API_KEY)).read() if not ret: return res = json.loads(ret) t = PrettyTable(["路線", "上車站", "下車站", "途徑站數", "首班車", "末班車", "預計時間", "步行距離"]) end = False count = 1 for transit in res["route"]["transits"]: t.add_row(["方案%s" %str(count),"","","","","", "","%s公里" % ( int(transit["walking_distance"]) / 1000.0)]) count += 1 for segment in transit.get("segments", []): if not segment["bus"]["buslines"]: end = True t.add_row(["","","","","","","",""]) else: names = [] d_stops = [] a_stops = [] durations = [] start_times = [] end_times = [] stops = [] for bus in segment["bus"]["buslines"]: names.append(bus["name"]) d_stops.append(bus["departure_stop"]["name"]) a_stops.append(bus["arrival_stop"]["name"]) durations.append(bus["duration"]) start_times.append(bus["start_time"][:2] + ":" + bus["start_time"][2:]) end_times.append(bus["end_time"][:2] + ":" + bus["end_time"][2:]) stops.append(bus["via_num"]) t.add_row([ "
".join(names), # "
".join([stop["name"] for stop in bus["via_stops"]]), "
".join(d_stops), "
".join(a_stops), "
".join(stops), "
".join(start_times), "
".join(end_times), "
".join(["%s分鐘" %(int(d)/60) for d in durations]), "", ]) if end == True: end = False t.add_row([ "---換乘---", "", "", "", "", "", "", "" ]) print t # for walk in segment["walking"]["steps"]: # print walk["instruction"] def info(args): city = get_city(args) ret = urllib2.urlopen("http://www.baike.com/wiki/%s" % city).read() if not ret: return summary = re.findall(r"<div class="summary">([sS]*?)</p>", ret)[0] summary = re.sub(r"<.*?>", "", summary) print (summary)def _main(): parser = argparse.ArgumentParser(description="城市信息查詢.") subparsers = parser.add_subparsers(title="操作命令") parser.add_argument("-k", "--keyword", type=str, help="關鍵詞") info_cmd = subparsers.add_parser("info", help="查詢城市簡介", description="查詢城市簡介") info_cmd.add_argument("city", nargs="?", help="查詢城市") info_cmd.set_defaults(func=info) place_cmd = subparsers.add_parser("place", help="查詢城市信息", description="查詢城市信息") place_cmd.add_argument("keyword", help="查詢的關鍵詞") place_cmd.add_argument("city", nargs="?", help="查詢城市") place_cmd.set_defaults(func=place) bus_cmd = subparsers.add_parser("bus", help="查詢公交信息", description="查詢公交信息") bus_cmd.add_argument("start", help="出發地") bus_cmd.add_argument("end", help="目的地") bus_cmd.add_argument("city", nargs="?", help="查詢城市") bus_cmd.set_defaults(func=bus) args = parser.parse_args() args.func(args)if __name__ == "__main__": _main()

08. 可視化數據結構

前言

使用PIL的可視化數據結構。

用法

from vds import StackVdss = Stack([1,24,23,423])tracer = StackVds(s)tracer.show()s.pop()tracer.show()

鏈表

from vds import LinkListVdsl = LinkList(1, [2,3,4,3])tracer = LinkListVds(l)tracer.show()l.delete(3, all=True)tracer.show()

二維數組

from vds import MatrixVdsarr = [ [1,2], [3,4,5,6], [7,8,9]]tracer = MatrixVds(arr)tracer.show()

09. 面向stackoverflow編程

前言

面向stackoverflow編程。

用法

準備工作

pip install stackitalias ???="python /path/to/wtf.py $(fc -ln -1);"

使用

測試腳本:error.py

root@vagrant-ubuntu-precise-64:/code# python error.pyTraceback (most recent call last): File "error.py", line 2, in <module> print(a[1])IndexError: list index out of range$ ???

輸出

Searching for: IndexError: list index out of range...Tags:1Question: How to define two-dimensional array in pythonAnswer:You"re technically trying to index an uninitialized array. You have to firstinitialize the outer list with lists before adding items; Pytho...2Question: Why list doesn"t have safe "get" method like dictionary?Answer:Ultimately it probably doesn"t have a safe `.get` method because a `dict` isan associative collection (values are associated with names) ...3Question: IndexError: list assignment index out of rangeAnswer:`j` is an empty list, but you"re attempting to write to element `[0]` in thefirst iteration, which doesn"t exist yet.Try the following ...4Question: How can I find the last element in a List<> ?Answer:If you just want to access the last item in the list you can do var item = integerList[integerList.Count - 1];to get...5Question: Getting a default value on index out of range in PythonAnswer:In the Python spirit of "ask for forgiveness, not permission", here"s one way: try: b = a[4] except IndexError:...Enter m for more, a question number to select, or q to quit:

源碼

import sysimport subprocess# alias ???="python /path/to/wtf.py $(fc -ln -1 | tail -n 1);"STACKIT_COMMAND = "stackit -s "%s"" def _main(): command = " ".join(sys.argv[1:]) try: o = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True) except subprocess.CalledProcessError, e: o = e.output errs = [] outputs = o.split("
") find = -1 for i, err in enumerate(outputs): if not err.startswith(" ") and not err.startswith("Traceback"): find = i break if find == -1: return errs = "".join(outputs[i:]) command = STACKIT_COMMAND % errs try: subprocess.call(command, shell=True) except: print("require stackit") if __name__ == "__main__": _main()

10. 加強型字元串

前言

100行的加強型字元串。

用法

from sstr import SuperStrprint SuperStr("{"name" : "mike"}").json() # {u"name": u"mike"}print SuperStr("1").int() # 1print SuperStr(pickle.dumps(object())).object() # <object object at 0x1043330d0>print SuperStr("123").list() # ["1", "2", "3"]print SuperStr("aabbbc").most_common(2) # [("b", 3), ("a", 2)]print SuperStr("exists").exists("t") # Trueprint SuperStr("ababab").findall("ab") # ["ab", "ab", "ab"]print SuperStr("ab,ab,ab").split(",") # ["ab", "ab", "ab"]print SuperStr("ab,ab,ab").sub(",", "") # abababprint SuperStr("ab,ab,ab").count("a") # 3print SuperStr("reverse").sort().reverse() # vsrreeeprint SuperStr("abc").permutations() # <itertools.permutations object at 0x1046a7830># capitalize# center# count# decode# encode# endswith# expandtabs# find# format# index# isalnum# isalpha# isdigit# islower# isspace# istitle# isupper# join# ljust# lower# lstrip# partition# replace# rfind# rindex# rjust# rpartition# rsplit# rstrip# split# splitlines# startswith# strip# swapcase# title# translate# upper# zfill

源碼

#-*- coding:utf-8 -*- import retry: import cPickle as pickleexcept: import pickleimport jsonimport itertoolsfrom collections import Counterclass SuperStr(object): def __init__(self, string=""): assert isinstance(string, str) or isinstance(string, unicode) self._str = string.encode("utf-8") if isinstance(string, unicode) else string def get(self): return self._str def int(self): return int(self._str) def json(self): return json.loads(self._str) def object(self): return pickle.loads(self._str) def list(self): return list(self._str) def reverse(self): self._str = self._str[::-1] return self def most_common(self, n): if hasattr(self, "counter"): return self.counter.most_common(n) self.counter = Counter(self._str) return self.counter.most_common(n) def exists(self, pattern): return re.search(pattern, self._str) is not None def findall(self, pattern, flags=0): return re.findall(pattern, self._str, flags) def split(self, pattern, maxsplit=0, flags=0): return re.split(pattern, self._str, maxsplit, flags) def sub(self, pattern, repl, count=0, flags=0): self._str = re.sub(pattern, repl, self._str, count, flags) return self def count(self, char): if hasattr(self, "counter"): return self.counter[char] self.counter = Counter(self._str) return self.counter[char] def permutations(self, r=None): return itertools.permutations(self, r) def sort(self): self._str = "".join(sorted(self._str)) return self def __str__(self): return self._str __repr__ = __str__ def __call__(self, *args, **kws): if callable(self._str): self._str = self._str() return self def __getattr__(self, key): if key in dir(str): self._str = getattr(self._str, key) return self self._str = super(SuperStr, self).__getattr__(key) return self def __radd__(self, s): self._str += str(s) return self __add__ = __radd__ def __mul__(self, num): return str(self) * 2 def __getitem__(self, given): self._str = self._str[given.start: given.stop: given.step] if isinstance(given, slice) else self._str[given] return selfif __name__ == "__main__": print SuperStr("{"name" : "mike"}").json() # {u"name": u"mike"} print SuperStr("1").int() # 1 print SuperStr(pickle.dumps(object())).object() # <object object at 0x1043330d0> print SuperStr("123").list() # ["1", "2", "3"] print SuperStr("aabbbc").most_common(2) # [("b", 3), ("a", 2)] print SuperStr("exists").exists("t") # True print SuperStr("ababab").findall("ab") # ["ab", "ab", "ab"] print SuperStr("ab,ab,ab").split(",") # ["ab", "ab", "ab"] print SuperStr("ab,ab,ab").sub(",", "") # ababab print SuperStr("ab,ab,ab").count("a") # 3 print SuperStr("reverse").sort().reverse() # vsrreee print SuperStr("abc").permutations() # <itertools.permutations object at 0x1046a7830> # capitalize # center # count # decode # encode # endswith # expandtabs # find # format # index # isalnum # isalpha # isdigit # islower # isspace # istitle # isupper # join # ljust # lower # lstrip # partition # replace # rfind # rindex # rjust # rpartition # rsplit # rstrip # split # splitlines # startswith # strip # swapcase # title # translate # upper # zfill


你想更深入了解學習Python知識體系,你可以看一下我們花費了一個多月整理了上百小時的幾百個知識點體系內容:

【超全整理】《Python自動化全能開發從入門到精通》筆記全放送


推薦閱讀:

Python數據分析及可視化實例之CentOS7.2+Python3x+Flask部署標準化配置流程
Flask 實現小說網站 (二)
Python實現3D建模工具
Flask模板引擎:Jinja2語法介紹
OpenCV:圖片操作基本知識(二)

TAG:Python | Python入门 | Python框架 |