Python:一周筆記

主題

  • 郵件處理
  • 日志模塊
  • pdf處理
  • md5
  • mongodb索引和聚合
  • excel 讀寫

1. 發(fā)送郵件模塊

這里指的郵件功能當(dāng)然不是指的是職場(chǎng)上所謂的郵件奏路,指的是程序運(yùn)行中希望將程序運(yùn)行的日志信息或者錯(cuò)誤捕獲信息發(fā)送給指定的收件人赴捞,通過郵件可以了解程序運(yùn)行的狀態(tài)或者出錯(cuò)信息。

關(guān)于郵件的基本概念憋肖,這里引用廖雪峰老師python教程中的郵件模塊:

假設(shè)我們自己的電子郵件地址是me@163.com,對(duì)方的電子郵件地址是friend@sina.com(注意地址都是虛構(gòu)的哈)档桃,現(xiàn)在我們用Outlook或者Foxmail之類的軟件寫好郵件昧廷,填上對(duì)方的Email地址粘拾,點(diǎn)“發(fā)送”窄锅,電子郵件就發(fā)出去了。這些電子郵件軟件被稱為MUA:Mail User Agent——郵件用戶代理。

Email從MUA發(fā)出去入偷,不是直接到達(dá)對(duì)方電腦追驴,而是發(fā)到MTA:Mail Transfer Agent——郵件傳輸代理,就是那些Email服務(wù)提供商疏之,比如網(wǎng)易殿雪、新浪等等。由于我們自己的電子郵件是163.com锋爪,所以丙曙,Email首先被投遞到網(wǎng)易提供的MTA,再由網(wǎng)易的MTA發(fā)到對(duì)方服務(wù)商其骄,也就是新浪的MTA亏镰。這個(gè)過程中間可能還會(huì)經(jīng)過別的MTA,但是我們不關(guān)心具體路線拯爽,我們只關(guān)心速度索抓。

Email到達(dá)新浪的MTA后,由于對(duì)方使用的是@sina.com的郵箱毯炮,因此逼肯,新浪的MTA會(huì)把Email投遞到郵件的最終目的地MDA:Mail Delivery Agent——郵件投遞代理。Email到達(dá)MDA后桃煎,就靜靜地躺在新浪的某個(gè)服務(wù)器上汉矿,存放在某個(gè)文件或特殊的數(shù)據(jù)庫里,我們將這個(gè)長(zhǎng)期保存郵件的地方稱之為電子郵箱备禀。

同普通郵件類似,Email不會(huì)直接到達(dá)對(duì)方的電腦奈揍,因?yàn)閷?duì)方電腦不一定開機(jī)曲尸,開機(jī)也不一定聯(lián)網(wǎng)。對(duì)方要取到郵件男翰,必須通過MUA從MDA上把郵件取到自己的電腦上另患。

所以,一封電子郵件的旅程就是:

發(fā)件人 -> MUA -> MTA -> MTA -> 若干個(gè)MTA -> MDA <- MUA <- 收件人

發(fā)送郵件使用到兩個(gè)模塊:smtplib, email
發(fā)送郵件分為兩步:

  1. email 構(gòu)造郵件
  2. smtplib 協(xié)議發(fā)送郵件

郵件發(fā)送主要涉及SMTP協(xié)議, 接收主要涉及POP 協(xié)議蛾绎、IMAP協(xié)議昆箕。
在學(xué)習(xí)之前:我們先看看一封郵件基本包含哪些基礎(chǔ)的東西:這里以QQ郵件為例:

1484399844411.png
  1. 收件人
  2. 發(fā)件人
  3. 郵件主題
  4. 郵件正文
  5. 郵件附件

所以使用郵件模塊的步驟大概也就是完成這些基本的構(gòu)造:
這里是使用QQ郵箱發(fā)送給163企業(yè)郵箱的一個(gè)實(shí)例:


import email
from email.mime.text import MIMEText
import smtplib
from email.header import Header

# 構(gòu)造郵件信息
msg = MIMEText('這是一份python自動(dòng)腳本郵件信息。', 'plain', 'utf-8') # 郵件正文

# QQ發(fā)給公司: 多了這步 server.starttls()
from_addr = "xie_wei_sh@foxmail.com" # 發(fā)件人
password = "****" # 發(fā)件人郵箱密碼
smtp_server = "smtp.qq.com"  # SMTP 服務(wù)器地址
port = 587  # SMTP 服務(wù)器端口
to_addr = "paul.xie@chinascope.com"  # 收件人

msg["From"] = Header("Python愛好者<{}>".format(from_addr))  # 顯示的郵件發(fā)件人
msg["To"] = Header("admin<{}>".format(to_addr))
msg["Subject"] = Header("來自SMTP的問候", "utf-8")  # 郵件主題

# 發(fā)送郵件 
server = smtplib.SMTP(smtp_server, port)
server.starttls()
server.set_debuglevel(1)
server.login(from_addr, password=password)
server.sendmail(from_addr, [to_addr], msg=msg.as_string())
server.quit()

上文看上去比較復(fù)雜租冠。有人問有沒有更清晰的方法鹏倘。更清晰的接口。
有的顽爹。
模塊:yagmail 第三方模塊纤泵,需要自己安裝

import yagmail

# 設(shè)置發(fā)送人信息及SMTP服務(wù)器和端口
yag = yagmail.SMTP(
    user="xie_wei_sh@foxmail.com",
    password="****",
    host="smtp.qq.com",
    port="587"
)

contents = u"系統(tǒng)發(fā)出警告,你已嚴(yán)重違規(guī)。"
yag.send(to=["paul.xie@chinascope.com","1156143589@qq.com"], subject="yagmail", contents=contents)

# 參數(shù)說明
to : 收件人镜粤,可以接受一個(gè)list 發(fā)送至多人

subject: 郵件主題

contents: 郵件正文捏题,默認(rèn)是文本信息玻褪,其實(shí)還可以接收各種常見的文件比如,*.jpg, *.docx, *.pdf 公荧,*.html 等信息带射,只需要設(shè)置完整路徑,或者同一目錄下文件名稱即可循狰。

  • 總結(jié)
  1. 發(fā)送郵件的步驟: 構(gòu)建郵件信息窟社,SMTP協(xié)議發(fā)送郵件
  2. 更友好的第三方庫yagmail
  3. 可能遇到的坑:SMTP協(xié)議服務(wù)器地址和端口不一致而產(chǎn)生的錯(cuò)誤;再一個(gè)可能是郵箱設(shè)置中沒有開啟SMTP晤揣,POP等服務(wù)

2. 日志

借用python最佳實(shí)踐中日志模塊的介紹:
關(guān)于日志的作用:

診斷日志 記錄與應(yīng)用程序操作相關(guān)的日志桥爽。例如,用戶遇到的報(bào)錯(cuò)信息昧识,可通過搜索診斷日志獲得上下文信息钠四。
審計(jì)日志 為商業(yè)分析而記錄的日志。從審計(jì)日志中跪楞,可提取用戶的交易信息缀去,并結(jié)合其他用戶資料構(gòu)成用戶報(bào)告或者用來優(yōu)化商業(yè)目標(biāo)。

其實(shí)print也能做到這些甸祭,那么為什么還使用日志模塊呢缕碎?

一句話:日志更友好的了解程序運(yùn)行中的信息或者錯(cuò)誤信息,方便了解程序運(yùn)行狀態(tài)以及報(bào)錯(cuò)信息池户。

那么如何使用日志模塊呢咏雌。logging

需要了解信息:

  1. 日志的級(jí)別
  2. 關(guān)于日志的基本概念:記錄器,處理器校焦,過濾器赊抖,格式化器
  3. 編寫常規(guī)的日志需要的步驟
  • 日志的級(jí)別:日志分等級(jí),設(shè)置好等級(jí)寨典,比設(shè)置好的級(jí)別大的才能在顯示
    • DEBUG
    • INFO
    • WARN
    • ERROR
    • CRITICAL

默認(rèn)日志名為root, 默認(rèn)日志級(jí)別為WARN

在程序中配置日志存在三種方法:

  • 使用INI文件配置
  • 使用字典或者JSON配置
  • 在程序源代碼中配置

這里以在程序源代碼中為例進(jìn)行配置:讀者要是感興趣可以了解其他配置方式:

import logging

logger = logging.getLogger("logger_name") # 記錄器
handler = logging.StreamHandler()  # 日志顯示在控制臺(tái)氛雪,還可以設(shè)置將日志信息輸出為文本形式FileHandler()
formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
        
handler.setFormatter(formatter) # 設(shè)置日志顯示方式
logger.addHandler(handler) # 添加處理器
logger.setLevel(logging.DEBUG) # 設(shè)置日志級(jí)別

logger.debug('often makes a very good meal of %s', 'visiting tourists') # 日志在程序中的使用

  • 總結(jié)
    基本步驟:
  • 創(chuàng)建logger
    logger = logging.getLogger("Your_logger_name")
    logger.setLevel(logging.DEBUG)
  • 創(chuàng)建handler
    logger_one = logging.StreamHandler()
    logger_one.setLevel(logging.INFO)
  • 創(chuàng)建Formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  • 配置Logger
    logger_one.setFormatter(formatter)
    logger.addHandler(logger_one)
  • 使用logger
    logger.info('info message')

3. pdf

存在這樣一個(gè)需求:想要抓取網(wǎng)頁上的信心,但發(fā)現(xiàn)所需要的信息在pdf中

在google中發(fā)現(xiàn)了其實(shí)存在將pdf信息轉(zhuǎn)換為字符串信息的這種模塊:pdfminer


# 讀取本地pdf轉(zhuǎn)化為字符串
from cStringIO import StringIO

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage


def convert_pdf_2_text(path):

    rsrcmgr = PDFResourceManager()
    retstr = StringIO()

    device = TextConverter(rsrcmgr, retstr, codec='utf-8', laparams=LAParams())
    interpreter = PDFPageInterpreter(rsrcmgr, device)

    with open(path, 'rb') as fp:
        for page in PDFPage.get_pages(fp, set()):
            interpreter.process_page(page)
        text = retstr.getvalue()

    device.close()
    retstr.close()

    return text

# 將數(shù)據(jù)讀入內(nèi)存在進(jìn)行處理
url_data = requests.get("http://www.sse.com.cn/disclosure/bond/announcement/bookentry/c/2768799626348021.pdf").content

data = StringIO(url_data)
parser = PDFParser(data)
document = PDFDocument(parser)
rercmgr = PDFResourceManager(document)
retstr = StringIO()
laparams = LAParams()
codec = 'utf-8'
device = TextConverter(rercmgr, retstr, codec=codec, laparams=laparams)
interpreter = PDFPageInterpreter(rercmgr, device)
for page in PDFPage.create_pages(document):
    interpreter.process_page(page)
text = retstr.getvalue()


# 返回的text 就能普通字符串的處理提取信息了耸成。

4. md5

from hashlib

md = hashlib.md5()
md.update("字符串")
md5.hexdigest()

// 現(xiàn)在的問題是想要根據(jù)一個(gè)字典數(shù)據(jù)形成一個(gè)hash, 以使得可以判斷字典數(shù)據(jù)沒有完全一致的报亩。

str = ("_".join("%s:%s" % (key, value) for key, value in dict_item.items() if key not in ("ct")) + "_" + str(number)).encode("utf-8")

md5.update(str)
md5.hexdigest()

5. 索引和聚合

遇到的問題是:能夠很好的對(duì)數(shù)據(jù)進(jìn)行判重處理。

之前的思路是:

  • 根據(jù)數(shù)據(jù)字段進(jìn)行數(shù)據(jù)唯一索引設(shè)置井氢,這樣處理其實(shí)去掉了好多為0的值弦追,因?yàn)樽ト〉暮枚鄶?shù)據(jù)都是0,為了需要數(shù)據(jù)的完備性花竞,這些數(shù)據(jù)其實(shí)也需要

之后的思路是:

  • 根據(jù)入庫的數(shù)據(jù)進(jìn)行生成md5值骗卜,將md5值設(shè)置為唯一索引值,完成了較好的去重操作
  1. 索引
coll_values.create_index([("md5_values", pymongo.ASCENDING)], unique=True)
  1. 聚合操作:對(duì)mongodb數(shù)據(jù)中數(shù)據(jù)進(jìn)行一些統(tǒng)計(jì)工作
  • match
  • group
  • limit
  • sort
query = [
    {
        "$match": {"key": code, "year": year, "type": type}
    },
    {
        "$group": {"_id": {"code": "$key", "year":"$year"}, "total": {"$sum":1}}
    }

]
total = []
for code in ["ACH", "IKGH", "ALN", "AMCN", "ATAI", "AXN", "ATV", "BIDU", "BITA", "BORN", "BSPM"]:
    for one in ["2011", '2012', '2013', '2014', "2015"]:
        A = Count(code=code, year=one, type="Annual", factor="Income Statement")
        result = A.aggregation()
        total.append(list(result))
pprint(total)

# 根據(jù)股票信息統(tǒng)計(jì)年份的數(shù)據(jù)數(shù)

6. excel 讀寫

需求是:想要將mongodb數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)入入excel中

使用到的模塊是:xlwt

關(guān)于excel的一些基本概念:

  1. Workbook : 工作簿
  2. sheet: 工作表
  3. cell: 單元格
1484444580203.png

一個(gè)workbook 可以包含多個(gè)sheet, 一個(gè)sheet中包含更多的行列組成的表格。

編寫程序的大概步驟也是:

  1. 實(shí)例化workbook
  2. 添加sheet
  3. 往單元格里面寫入內(nèi)容
  4. 保存文件
import xlwt

wb = xlwt.Workbook()
ws = wb.add_sheet('A Test Sheet')

ws.write(0, 0, 1234.56)  # 第一行第一列寫入123.56
ws.write(2, 0, 1)   # 第三行第一列寫入 1
ws.write(2, 1, 1)   # 第三行第二列寫入 1
ws.write(2, 2, xlwt.Formula("A3+B3"))  # 第三行第三列是前面值之和

wb.save('example.xls')  # 保存為文件名example.xls

所以:xlwt的基本使用就是往單元格中進(jìn)行內(nèi)容的寫入寇仓。

// mongodb 實(shí)例

from pymongo import MongoClient
from xlwt import Workbook
from xlwt import easyxf  # 可以定義字體举户,顏色等樣式


class MongoToXls(object):

    def __init__(self, collection, name):
        self.work_book = collection
        self.sheet_name = name
        self.wb = Workbook()
        self.ws = [self.wb.add_sheet(one) for one in self.sheet_name]
        self.style = easyxf("align: vert centre, horiz center")
        pass

    def info(self, number):
        self.contents = list(self.work_book[number].find())
        self.headers = [key for key in self.contents[0].keys()]
        rows = len(self.contents)
        columns = len(self.headers)
        return rows, columns

    def write_header(self, number):
        ws = self.ws[number]
        _, columns = self.info(number)
        for i in range(0, columns):
            ws.write(0, i, self.headers[i], style=self.style)

    def write_content(self, number):
        ws = self.ws[number]
        rows, columns = self.info(number)
        if rows >= 65536:
            rows = 65535
        for j in range(1, rows + 1):
            for k in range(0, columns):
                ws.write(j, k, str(self.contents[j - 1][self.headers[k]]), style=self.style)

    def save(self):
        name = "_".join(self.sheet_name) +"2"+ str(".xls")
        self.wb.save(str(name))

collection1 = MongoClient()["db5"]["base"]
collection2 = MongoClient()["db5"]["items"]
collection3 = MongoClient()["db5"]["values"]
collection = [collection1, collection2, collection3]
name = ["base", "items", "values"]

A = MongoToXls(collection=collection, name=name)
for number in range(len(collection)):
    print A.info(number)
    A.write_header(number)
    A.write_content(number)
A.save()

總結(jié):

  1. 根據(jù)數(shù)據(jù)獲取行和列數(shù)
  2. 先寫入header信息
  3. 再兩重循環(huán)寫入內(nèi)容值

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市遍烦,隨后出現(xiàn)的幾起案子俭嘁,更是在濱河造成了極大的恐慌,老刑警劉巖服猪,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件供填,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡罢猪,警方通過查閱死者的電腦和手機(jī)近她,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膳帕,“玉大人粘捎,你說我怎么就攤上這事∥2剩” “怎么了攒磨?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)汤徽。 經(jīng)常有香客問我娩缰,道長(zhǎng),這世上最難降的妖魔是什么谒府? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任拼坎,我火速辦了婚禮,結(jié)果婚禮上完疫,老公的妹妹穿的比我還像新娘泰鸡。我一直安慰自己,他們只是感情好趋惨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惦蚊,像睡著了一般器虾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹦锋,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼氢哮。 笑死默垄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播库正,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼曲楚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了褥符?” 一聲冷哼從身側(cè)響起龙誊,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喷楣,沒想到半個(gè)月后趟大,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铣焊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年逊朽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曲伊。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叽讳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熊昌,到底是詐尸還是另有隱情绽榛,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布婿屹,位于F島的核電站灭美,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏昂利。R本人自食惡果不足惜届腐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜂奸。 院中可真熱鬧犁苏,春花似錦、人聲如沸扩所。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祖屏。三九已至助赞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間袁勺,已是汗流浹背雹食。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留期丰,地道東北人群叶。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓吃挑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親街立。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舶衬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 主要介紹幾個(gè)用到的python模塊的使用方法。python 含有豐富的內(nèi)置和第三方庫几晤,企圖全部掌握并精通那是不可能...
    謝小路閱讀 1,065評(píng)論 3 20
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個(gè)目的:監(jiān)視代碼中變量的變化情況约炎,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計(jì)分析...
    時(shí)待吾閱讀 4,975評(píng)論 0 6
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)蟹瘾,斷路器圾浅,智...
    卡卡羅2017閱讀 134,639評(píng)論 18 139
  • 那一年的南國(guó)众雷,下了雪灸拍,很大很大的雪,飄飄灑灑砾省,肆意飛揚(yáng)鸡岗。整個(gè)天地純潔無比! 南蝶鐘愛紅衣编兄,一身紅衣如火轩性,紅與白,她...
    蝶雪微明閱讀 682評(píng)論 6 14
  • 目標(biāo):不停追求(卓)狠鸳、不斷翱翔(菲) 晨讀半個(gè)小時(shí)揣苏。 做飯。 中午看小說件舵。 有點(diǎn)煩卸察,我的眼鏡又跑了。 下午練習(xí)乒乓...
    逆風(fēng)追夢(mèng)人閱讀 90評(píng)論 0 0