本來是不會想要分享發(fā)出來的。
但是因為在 comment 區(qū)發(fā)了解法,然后有人問解釋一下這行代碼,所以就解釋了一下。
本著解釋都解釋了,敲了那么多行字,所以不如分享出來給更多的人看到。
(the)Problem
[問題] :Leetcode#1470. Shuffle the Array
[描述] :
給你一個數(shù)組 nums,數(shù)組中有 2n 個元素,按 [x1,x2,...,xn,y1,y2,...,yn] 的格式排列。
請你將數(shù)組按 [x1,y1,x2,y2,...,xn,yn] 格式重新排列,返回重排后的數(shù)組。
示例 1: 輸入:nums = [2,5,1,3,4,7], n = 3 輸出:[2,3,5,4,1,7] 解釋:由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7,所以答案為 [2,3,5,4,1,7]
示例 2:N/A
示例 3: 輸入:nums = [1,1,2,2], n = 2 輸出:[1,2,1,2]
[提示] : 1 <= n <= 500 nums.length == 2n 1 <= nums[i] <= 10^3
來源:力扣( LeetCode ) 鏈接: https://leetcode-cn.com/problems/shuffle-the-array 著作權歸領扣網(wǎng)絡所有。商業(yè)轉載請聯(lián)系官方授權,非商業(yè)轉載請注明出處。
Solution
我的一行解法: class Solution: def shuffle(self, nums: List[int], n: int) -> List[int]: return reduce(add, zip(nums[:n], nums[n:]))
解釋
對這一行代碼的 explain:
https://leetcode.com/problems/shuffle-the-array/discuss/751957/Python-one-line-(Memory-Usage-less-then-100.00):-the-more-pythonic-way/629230
背景:從 java 轉 python 的初學者我想實現(xiàn)的目的是: 在這三個方法中可以怎樣選擇性執(zhí)行 one() or two() or three()? 我百度了下,可以創(chuàng)建測試類,但是它會輸出一個測試報告,且會進行斷言,而我的目的不是進行單元測試,是要在一個 py 文件里單獨執(zhí)行不同的方法 還可以在 pycharm 里使用 shift+alt+e 執(zhí)行代碼片段,但是我會些一些邏輯在里面,還有 import,這個方法也不行 對比 java,有 junit 可以實現(xiàn): 可以分別執(zhí)行這三個方法,那么輪子眾多的 python 也一定有相應的方法才對,只是我沒有找到,所以請教各位,我可以怎么做?
公司打算自己做一個圖像識別的東西 ,用顯卡計算
但是圖像比較大,希望能減少計算時間
有沒有做過的大佬推薦下,怎么搭配顯卡最好
功能很簡單,就是用戶通過表單 'POST' 提交用戶名,然后根據(jù)用戶名生成一個用戶頭像的 portrait.png 的 圖片返回。 方式一:是把已經生成好的頭像圖片,返回給頁面,圖片可以正常顯示,也可以另存。 def generate_portrait(): user_img = Image.open('portrait.png') out = BytesIO() user_img.save(out, 'PNG') out.seek(0) return send_file(out, mimetype='image/png') 方式二:如果是用戶通過表單提交用戶名,生成 portrait.png 之后,立即返回給頁面。在頁面上,圖片可以顯示,但是無法保存(要么提示網(wǎng)絡錯誤,要么保存到硬盤也打不開) def generate_portrait(): form = PortraitForm() if form.validate_on_submit(): ... some code to generate portrait.png and save to local disk ... user_img = Image.open('portrait.png') out = BytesIO() user_img.save(out, 'PNG') out.seek(0) return send_file(out, mimetype='image/png') ....
看起來方式一、和方式二并沒有大的區(qū)別,方式二我也把 portrait.png 先落盤存到磁盤上,再讀取返回,也不行。
方式一是把圖片生成和返回在 2 個 request 里完成的,方式二就是在 1 個 request 里同時“生成”圖片并“返回”圖片
這個問題搜了不少地方,都沒有看到類似的問題和解決方法。不清楚問題到底處在哪兒了
去年這個時候開始的想法,獨立開發(fā)了一年,期間在公司的一些項目里也用上了?,F(xiàn)在感覺可以見人了,歡迎大家來使用 & 噴我代碼,也歡迎 ISSUE/PR ??。
https://github.com/abersheeran/index.py
我開始開發(fā) Index.py 的時候就一個目的——不想再去折騰路由。然后才逐漸增加功能。
功能和 FastAPI 高度重合,開發(fā)也幾乎是同一時期……但我兩肯定沒抄對方的,我相信它的作者看不懂中文文檔,我英文也挺菜的,FastAPI 沒火之前我壓根不知道還有人在弄類似的項目。
不過大型項目肯定我比它快,因為我尋找路由是 O(1),其他基于 starlette 的框架都是 O(n)。說實話,Python 社區(qū)的 web 框架,路由系統(tǒng)全部用的遍歷,不知道咋想的。我以前一直以為大家都是前綴樹……
總之??希望大家有空來用用。
按照文檔上 pyautogui 快捷鍵代碼為 pyautogui.hotkey('command', 'r') 但是不知道為何我的電腦上 command 沒有點擊,只執(zhí)行了 r 變?yōu)榱溯敵鑫谋?目前處理方式為,手動模擬快捷鍵 for arg in args: pyautogui.keyDown(arg) for arg in args: pyautogui.keyUp(arg)
但是很多時候有快捷鍵無效的情況
需求:同一局域網(wǎng)目標服務器 Mac 名是 tommac,用戶 tom,ip:192.168.50.4,本地服務器 Mac 名是 jasonmac,用戶 jason.需要把 /Users/tom/Documents/working/purchase.xlsx 復制到 /Users/jasonmac/Documents/working
嘗試了 pysmb 和 paramiko 兩個庫
前者報 not connected,后者報 Error reading SSH protocol banner.總之就是各種連接不上目標服務器.(確認目標服務器已經打開共享,并且在網(wǎng)絡里可以訪問) 同時我也有點搞不清楚,mac 的計算機名到底應該是 jason 這種,還是 jason.local,似乎嘗試了也都錯.端口不管是官網(wǎng)范例的 139,還是很多人用的 445 都不行.
stackoverflow 上看了好半天都研究不出,有沒有熟悉的朋友說下可能的原因?或者推薦下自己熟悉的庫 預先感謝大家!
下面是 pysmb 時候的一段代碼(import 部分忽略)
share_name = "jason" user_name = "jason" password = "57777" local_machine_name = "tommac" server_machine_name = "jasonmac" server_ip = "192.168.50.4"
conn = SMBConnection(user_name, password, local_machine_name, server_machine_name, use_ntlm_v2=True) assert conn.connect(server_ip, 139) print('connected')
file_obj = tempfile.NamedTemporaryFile() file_name = file_obj.name file_attributes, copysize = conn.retrieveFile(share_name, "/Documents/working/purchase.xlsx", file_obj) print(copysize) file_obj.close() shutil.copy(file_name, "/Users/tom/Documents/working/purchase.xlsx") conn.close()
有償找 python 爬蟲大神,需要網(wǎng)站數(shù)據(jù) 微信 ahui580000
def loggingDecorator(func): """記錄日志的裝飾器"""
def wrapperLogging(*args, **kwargs): logging.info("開始執(zhí)行 %s() ..." % func.__name__) func(*args, **kwargs) logging.info("%s() 執(zhí)行完成!" % func.__name__) return wrapperLogging
def showInfo(*args, **kwargs): print("這是一個測試函數(shù),參數(shù):", args, kwargs)
decoratedShowInfo = loggingDecorator(showInfo)
decoratedShowInfo('arg1', 'arg2', kwarg1=1, kwarg2=2)
我期待的結果是:
INFO:root:開始執(zhí)行 showInfo() ...
這是一個測試函數(shù),參數(shù): ('arg1', 'arg2') {'kwarg1': 1, 'kwarg2': 2}
INFO:root:showInfo() 執(zhí)行完成!
但實際結果是:
這是一個測試函數(shù),參數(shù): ('arg1', 'arg2') {'kwarg1': 1, 'kwarg2': 2}
INFO:root:開始執(zhí)行 showInfo() ...
INFO:root:showInfo() 執(zhí)行完成!
或者:
INFO:root:開始執(zhí)行 showInfo() ...
INFO:root:showInfo() 執(zhí)行完成!
這是一個測試函數(shù),參數(shù): ('arg1', 'arg2') {'kwarg1': 1, 'kwarg2': 2}
請問各位這是為何啊
Mac 下跑 Python,調用 gsheets 庫
相關的 Google Drive 和 Google Sheets API 都已經 Enable, 下載了 client_secret.json,
運行相關 Python 程序, 且登錄相關頁面后,完成驗證,顯示 The authentication flow has completed.
但 terminal 提示 ConnectionResetError: [Errno 54] Connection reset by peer
網(wǎng)上有搜索到可能和 OpenSSL 有關,但不確定.這個是被和諧的意思嗎? 系統(tǒng)是 Catalina,還需要手動升級 OpenSSL 嗎?
標題是抖音里一個推廣 Python 課程的視頻宣傳語。
我想利用暑假學習計算機語言,從什么開始學起比較好呢?另外,我是一個文科生。
先上代碼 from concurrent.futures import ThreadPoolExecutor import time from loguru import logger def func1(x): time.sleep(2) return x def func2(): my = [] exe = ThreadPoolExecutor() for r in exe.map(func1,range(10)): my.append(r) exe.shutdown() logger.info(my) def func3(): exe = ThreadPoolExecutor(1) exe.submit(func2) # 這里我想先返回 1,然后異步執(zhí)行函數(shù) haha2,但是我如果設置了 wait 為 False 的話 haha2 就不會執(zhí)行, # 不設置的話得等到 haha2 執(zhí)行完畢才能返回 1,我該怎么做 exe.shutdown(wait=False) return 1 if __name__ == '__main__': res = func3() print(res)
我現(xiàn)在的需求是有三個函數(shù),函數(shù) 2 中會使用 ThreadPoolExecutor 去執(zhí)行函數(shù) 1(為了提升效率),函數(shù) 3 中會執(zhí)行函數(shù) 2 并返回一個值,但是我想函數(shù) 3 先返回值就給一個 ThreadPoolExecutor(1)并且設置 wait 為 False,但是這樣函數(shù) 2 并沒有執(zhí)行,請問我該如何實現(xiàn)我得目的。。。還是說 ThreadPoolExecutor 不適用這種場景,那么我應該怎么辦呢
環(huán)境: python-3.6.5 djangorestframework-3.10.3 django-2.2.3
這是我自定義的一些異常:
繼承關系是:WechatPaymentError -> BaseWechatError -> Exception 但是在統(tǒng)一處理異常時卻出現(xiàn)了這樣的情況:
通過 type(exc)可以看到 exc 是 WechatPaymentError 的實例, 但是對 WechatPaymentError 和 BaseWechatError 的 isinstance 判斷都是 False
數(shù)據(jù)如下:ts_code trade_date open high low close pre_close change pct_chg vol amount 0 600585.SH 20200729 59.60 60.80 59.05 60.68 59.90 0.78 1.3022 319148.23 1923818.3501 600585.SH 20200728 60.18 60.95 59.45 59.90 59.76 0.14 0.2343 284117.71 1711289.7432 600585.SH 20200727 59.62 60.90 59.14 59.76 58.85 0.91 1.5463 362054.35 2171456.7753 600585.SH 20200724 60.46 60.94 58.20 58.85 61.05 -2.20 -3.6036 443699.05 2636469.5884 600585.SH 20200723 60.08 61.50 59.11 61.05 60.97 0.08 0.1312 437532.84 2641867.877.. ... ... ... ... ... ... ... ... ... ... ... 133 600585.SH 20200108 53.00 53.38 52.60 52.69 53.48 -0.79 -1.4772 232324.76 1228341.855134 600585.SH 20200107 53.12 54.13 53.12 53.48 53.32 0.16 0.3001 234783.33 1256641.148135 600585.SH 20200106 54.01 54.54 53.05 53.32 54.68 -1.36 -2.4872 343560.81 1845565.954136 600585.SH 20200103 56.00 56.10 54.44 54.68 55.80 -1.12 -2.0072 288642.12 1585798.292137 600585.SH 20200102 55.30 57.75 55.03 55.80 54.80 1.00 1.8248 411235.67 2306726.977設置 df.sort_index(ascending = True) 或 false 索引 0 都是指向 20200729 這行數(shù)據(jù) 怎么能把 0 指向 20200102 這行數(shù)據(jù)呢?
hello,小伙伴們,大家好,今天給大家推薦的開源項目是: BaoTa ,這個開源項目主要是以 Linux 面板是提升運維效率的服務器管理軟件,支持一鍵 LAMP/LNMP/集群 /監(jiān)控 /網(wǎng)站 /FTP/數(shù)據(jù)庫 /JAVA 等 100 多項服務器管理功能,感興趣的小伙伴可以自己去體驗一下。
以上是部分效果展示,感興趣的小伙伴可以嘗試應用一下,監(jiān)控自己的爬蟲,監(jiān)控 Linux 上數(shù)據(jù)庫或者是其它服務,可以更好的利用 CPU 的資源。
開源地址: https://github.com/aaPanel/BaoTa
今天的推薦不知道大家喜歡嗎?如果你們喜歡話,請在文章底部留言或點贊,以表示對我的支持,你們的留言,點贊,轉發(fā)關注是我持續(xù)更新的動力哦!
關注公眾號回復:" 1024 ",免費領取一大波學習資源,先到先得哦!
hello,小伙伴們,大家好,今天給大家介紹的開源項目是: Python3-Spider ,這個開源項目主要寫的是關于 Python 模擬登陸各大網(wǎng)站 包含但不限于:滑塊驗證、拼多多、美團、百度、bilibili 、大眾點評、淘寶等,感興趣的小伙伴可以自己 clone 下來自己動手實踐一下。
[推薦] 爬蟲練習網(wǎng)
一個很不錯的爬蟲練習題網(wǎng),內涵十幾個爬蟲題目,由淺到深涵蓋 ip 反爬 、 js 反爬 、 字體反爬 、 驗證碼 等題目。安利給大家,博主已擼完。 登錄網(wǎng)址 http://www.glidedsky.com/login 題分排行榜 http://www.glidedsky.com/rank
文書網(wǎng) app
《 入門級安卓逆向 - 文書網(wǎng) app 爬蟲教程 》
涵蓋的內容不少,感興趣的小伙伴可以下載使用一下。
開源地址: https://github.com/wkunzhi/Python3-Spider
今天的推薦不知道大家喜歡嗎?如果你們喜歡話,請在文章底部留言或點贊,以表示對我的支持,你們的留言,點贊,轉發(fā)關注是我持續(xù)更新的動力哦!
關注公眾號回復:" 1024 ",免費領取一大波學習資源,先到先得哦!
下面是網(wǎng)上的一個入庫 sqlite3 的,我要原樣改成入庫 mysql 的。 功能就是插入文章,在插入文章前需要得到文章分類的 id,如果有就根據(jù)分類名查詢到分類 id, 如果沒有就根據(jù)得到的資料生成分類并取得 id. 下面 sqlite3 的是可以的
問題是 我要改成 mysql 的就不行了。具體看后面代碼。 class BookspiderPipeline(object): def __init__(self): DBpath = os.getcwd() + '/db.sqlite3' self.con = sqlite3.connect(DBpath) self.cur = self.con.cursor() def process_item(self, item, spider): self.cur.execute("SELECT id FROM books_tag WHERE tagname = ?", (item['categoryName'],)) tagID = self.cur.fetchone() if not tagID: self.cur.execute("INSERT INTO books_tag (tagname) VALUES (?)", (item['categoryName'],)) self.con.commit() self.cur.execute("SELECT id FROM books_tag WHERE tagname = ?", (item['categoryName'],)) tagID = self.cur.fetchone() tagID = tagID[0] print(tagID) self.cur.execute("SELECT id FROM books_book WHERE title = ?", (item['bookName'],)) bookID = self.cur.fetchone() if not bookID: self.cur.execute(''' INSERT INTO books_book (title, cover, author, intro, tag_id) VALUES (?,?,?,?,?) ''', (item['bookName'], item['cover'], item['author'], item['intro'], tagID)) self.con.commit() self.cur.execute("SELECT id FROM books_book WHERE title = ?", (item['bookName'],)) bookID = self.cur.fetchone() bookID = bookID[0] print(bookID) self.cur.execute('''INSERT INTO books_chapter (number, title, content, book_id) VALUES (?,?,?,?)''', (int(item['number']), item['chapterName'], item['chapterContent'], bookID)) self.con.commit() return item
我的代碼: class ScMySqlPipeline(object): def __init__(self): dbargs = dict( host = '127.0.0.1', user = 'root', passwd = 'mysqlpasswd', db = 'info2222', port = 3306, cp_reconnect = True, cursorclass = pymysql.cursors.DictCursor, charset = 'utf8mb4', use_unicode = True, ) self.dbpool = adbapi.ConnectionPool('pymysql', **dbargs) def process_item(self, item, spider): #代碼執(zhí)行到這里就出問題了。應該下面代碼不對。 #下面是 先判斷有沒有這個分類,根據(jù)分類名查詢數(shù)據(jù)庫,如果有就把這個分類的 id 取出來賦值給 category_id 以便于在后面插入文章時用到這個分類 id, 如果沒有的話就插入這個分類然后再得到她的分類 id 值 conn.execute("""select id from aainfo_category where name = %s""", (item['fenlei'], )) category_id = conn.fetchone() if not category_id: conn.execute("INSERT INTO aainfo_category (`name`, `slug`, `chaodai`, `num`, `description`, `jianjie`, `weburl`) VALUES (%s, %s, %s, %s, %s, %s, %s)", (item['category_name'], item['category_slug'], item['category_chaodai'], 0, item['category_description'], item['category_jianjie'], item['category_weburl'])) #conn.commit() conn.execute("""select id from aainfo_category where name = %s""", (item['fenlei'], )) category_id = conn.fetchone() print (category_id) category_id = category_id[0] print (category_id) if isinstance(item, vodItem): query = self.dbpool.runInteraction(self.insert_into_info, item).addErrback(self.handle_error) return item
self.insert_into_info 這個函數(shù)是文章插入 mysql 的代碼。需要用到分類的 id ,所以上面代碼取得分類的 id 的功能。不知那里有錯?請各位朋友指點一下。謝謝。
本期我們和陳錚聊了 Python3 相關的話題。
本期發(fā)布地址: https://pythonhunter.org/episodes/ep16
itunes 美國區(qū) 已上架,itunes 中國區(qū)會稍晚一些通過審核之后發(fā)布
喜馬拉雅發(fā)布地址: https://www.ximalaya.com/keji/24821511/320705677
推薦使用泛用型客戶端收聽本期播客。
捕蛇者說 TG 討論組: 點擊鏈接加入
捕蛇者說制作團隊和往期節(jié)目嘉賓都在這里,快來 Happy~
本期主播 adamwen laixintao Manjusaka
本期嘉賓 liamchzh
TimeLine 00:00:30 正片開始-嘉賓介紹 00:01:27 聊一聊自己喜歡的 Python3 特性 00:02:00 dataclasses 00:04:09 在面向對象的開發(fā)過程中何時會用到 frozen 這個特性 00:05:19 使用 datacalsses 時在 __init__ 中定義的參數(shù)屬于 class 參數(shù)還是對象參數(shù)? 00:12:10 有沒有一個方法能夠在 __init__ 方法中調用 dataclasses 的 __init__ 方法? 00:15:10 Python 的執(zhí)行代碼有必要獲取機器有多少核心嘛,因為它可以通過外部在控制多線程模型? 00:16:46 有序字典 00:17:18 Django choices 00:19:00 金融驗簽之參數(shù)順序 00:21:15 關于對接支付接口的一些吐槽 00:22:08 兼顧一批數(shù)據(jù)的有序和快速查找 00:23:08 f-String 00:24:52 如果將 f-String 的 f 前綴變成后綴 00:26:02 type hint 00:27:22 type hint 在 CI 中的應用 00:29:16 在真實使用過程中是整理 CI 的時間消耗與 CI 幫助我們修復 BUG 的時間哪個更多一點 00:30:00 Python3 中覺得不爽的點 00:30:09 pep572 海象操作符 00:30:57 (不局限于 Python3 )線上調試工具缺乏 00:33:48 3 除以 2 的結果是什么 00:34:42 Python3 sort 去掉了 cmp 參數(shù) 00:35:32 Python3 的升級偏向于某些語法糖(相對于調試工具等方面) 00:37:26 Python2 遷移至 Python3 過程中的問題 00:38:01 遷移方式 00:41:28 如何在之遷移了部分語法的情況下再 Python3 中進行測試 00:43:46 分層遷移過程中的一些細節(jié) 00:45:14 何時停止對 Python2 的測試 00:48:06 關于面試會提到的 Python3 與 Python2 如何同時兼容的問題的討論 00:49:20 關于 Mercurial 遷移文章的討論 00:53:16 關于遷移后測試的一些補充 00:55:56 Python2 遷移至 Python3 之字符串的一個坑 00:57:28 Unicode 相關討論以及 Python 中的字符串和 Unicode 01:06:45 更多關于 Python2 中坑的舉例(吐槽) 01:09:01 對現(xiàn)在需要做 Python3 遷移工作的人的建議 01:15:37 Python3 協(xié)程的相關討論( Manjusaka 瘋狂輸出) 01:28:59 推薦環(huán)節(jié) 01:34:11 laike9m 客串感謝打賞聽眾 01:36:46 結束詞+音樂
Guest Recommendation 00:02:00 python3-dataclasses 00:26:02 PEP 484 -- Type Hints 00:30:09 PEP 572 -- Assignment Expressions 00:38:34 nstagram PyCon 2017 00:48:58 Mercurial's Journey to and Reflections on Python 3 01:01:56 Pragmatic Unicode 01:12:35 caniusepython3 01:29:11 A Philosophy of Software Design 01:29:29 A Philosophy of Software Design 作者 YouTube 演講 01:31:01 Microservice Patterns 01:31:13 TCP/IP 詳解 卷 1:協(xié)議 01:31:29 vim-which-key 01:33:04 kafka-documentation-desgin
先看代碼 # Arg 只是接口,實際使用中用到的是 Arg 的各種實現(xiàn)的實例,但實在沒有的話會把 Arg 實例化作為參數(shù) class Arg: def method_a(self): pass def method_b(self): pass # 我個人習慣是簽名處實例化 # 在簽名處初始化例子 class MyDummy: def __init__(self,arg=Arg()): self.arg = arg # 我看到項目總其他的代碼如下 # 默認為 None,在函數(shù)執(zhí)行時候再初始化 class OtherDummy: def __init__(self,arg=None): if arg == None: self.arg = Arg() # 一般使用下,大家都沒問題 my_dummy = MyDummy() other_dummy = OtherDummy() # MyDummy 會出問題的情況 my_dummy = MyDummy(arg = None) other_dummy = OtherDummy(arg = None) # 我是想不出為什么要用第二種寫法?難道是 PEP 推薦?
想問一下,大家看法和建議?
linux 中可以安裝 win32com 庫么,求指點
聲明
你感覺侵權的話,聯(lián)系我,我想辦法刪帖
本篇文章轉載于公眾號"編碼天空"
已知條件
1.瑞數(shù)所有版本共用一個指紋代碼,不然無法做風控,所以猜測指紋代碼所有通用。已經驗證文書網(wǎng),藥監(jiān)局,商標局
2.知己知彼,該產品是根據(jù) 80T 解密后,將各個特征值分類,部分值(比如指紋)屬于高風險的就全部 ban 掉。是否只要我指紋這種理論上唯一的東西改掉就沒問題了?已經修改了( canvas+webrtc )
3.實際上指紋也沒啥用,我們公司批量裝機時指紋高度一致。
4.拓展一下思維,流水線生產出的安卓手機是否指紋也高度一致?
這些代碼有啥用
1.假如你們家 web 端產品很多人用,那么你用同樣的代碼獲取到指紋并且保存一份。當你采集某網(wǎng)站遇到了某數(shù),能否注入進去,故意觸發(fā)反爬呢? A 網(wǎng)站的用戶莫名其妙打不開 B 網(wǎng)站,是不是 B 網(wǎng)站會承受一些投訴亦或者影響到自己家付費用戶?
2.你也可以做一個反爬產品,只要你混淆的好。
代碼如下
canvas 指紋: function getcanvas(){ try { var canvasEle = window['document']['createElement']('canvas'); if (canvasEle && canvasEle['getContext']) { canvasEle['width'] = 200; canvasEle['height'] = 50; canvas2d = canvasEle['getContext']('2d'); canvas2d['textBaseline'] = "top"; canvas2d['font'] = "18px 'Arial'"; canvas2d['fillStyle'] = '#f82'; canvas2d['fillRect'](0, 0, 100, 30); canvas2d['fillStyle'] = '#17e'; canvas2d['fillText']('ActiveXObject', 3, 16); canvas2d['fillStyle'] = 'rgba(240,110,53,0.4)'; canvas2d['fillText']('ActiveXObject', 5, 18); imageBase64Str = canvasEle['toDataURL'](); console.log(imageBase64Str); } catch (err) { // TODO 異常操作 } }
音頻指紋: function audioContext(){ try { var audioArr = []; shaderSource1 = 'attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}'; shaderSource2 = 'precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}'; var canvasEle = window['document']['createElement']('canvas'); var webGLRenderingContext = canvasEle.getContext('webgl'); createBuffer = webGLRenderingContext['createBuffer'](); webGLRenderingContext['bindBuffer'](webGLRenderingContext['ARRAY_BUFFER'], createBuffer); _$ma = new window['Float32Array']([-.2, -.9, 0, .4, -.26, 0, 0, .813264543, 0]); webGLRenderingContext['bufferData'](webGLRenderingContext['ARRAY_BUFFER'], _$ma, webGLRenderingContext['STATIC_DRAW']); createBuffer['itemSize'] = 3; createBuffer['numItems'] = 3; createProgram = webGLRenderingContext['createProgram'](), vertex_shader = webGLRenderingContext['createShader'](webGLRenderingContext['VERTEX_SHADER']); webGLRenderingContext['shaderSource'](vertex_shader, shaderSource1); webGLRenderingContext['compileShader'](vertex_shader); fragment_shader = webGLRenderingContext['createShader'](webGLRenderingContext['FRAGMENT_SHADER']); webGLRenderingContext['shaderSource'](fragment_shader, shaderSource2); webGLRenderingContext['compileShader'](fragment_shader); webGLRenderingContext['attachShader'](createProgram, vertex_shader); webGLRenderingContext['attachShader'](createProgram, fragment_shader); webGLRenderingContext['linkProgram'](createProgram); webGLRenderingContext['useProgram'](createProgram); createProgram['vertexPosAttrib'] = webGLRenderingContext['getAttribLocation'](createProgram, 'attrVertex'); createProgram['offsetUniform'] = webGLRenderingContext['getUniformLocation'](createProgram, 'uniformOffset'); webGLRenderingContext['enableVertexAttribArray'](createProgram['vertexPosArray']); webGLRenderingContext['vertexAttribPointer'](createProgram['vertexPosAttrib'], createBuffer['itemSize'], webGLRenderingContext['FLOAT'], !1, 0, 0); webGLRenderingContext['uniform2f'](createProgram['offsetUniform'], 1, 1); webGLRenderingContext['drawArrays'](webGLRenderingContext['TRIANGLE_STRIP'], 0, createBuffer['numItems']); if (webGLRenderingContext['canvas'] != null) audioArr.push(webGLRenderingContext.canvas['toDataURL']()); if (webGLRenderingContext['getShaderPrecisionFormat']) { vertex_shaders = [webGLRenderingContext['VERTEX_SHADER'], webGLRenderingContext['FRAGMENT_SHADER']], high_floats = [webGLRenderingContext['HIGH_FLOAT'], webGLRenderingContext['MEDIUM_FLOAT'], webGLRenderingContext['LOW_FLOAT'], webGLRenderingContext['HIGH_INT'], webGLRenderingContext['MEDIUM_INT'], webGLRenderingContext['LOW_INT'] ]; for (h = 0; h < vertex_shaders.length; h++) { for (i = 0; i < high_floats.length; i++) { _$MO = webGLRenderingContext['getShaderPrecisionFormat'](vertex_shaders[h], high_floats[i]); audioArr.push(_$MO['rangeMin'], _$MO['rangeMax'], _$MO['precision']); } } } console.log(audioArr); } catch (err) { // TODO 異常操作 } }
hello,小伙伴們,大家好,今天給大家介紹的開源項目是: loguru ,這個開源項目是一個 Python 簡易日志庫,這個開源項目的宗旨是通過添加一系列有用的功能來解決標準記錄器的注意事項,從而減少 Python 日志記錄的痛苦。
我們使用 logging 的配置方法基本上是這樣的: import logging logging.basicConfig( filename='test.log', level=logging.DEBUG, format='[line:%(lineno)d] - %(funcName)s: %(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S', )
使用官方自帶的 logging 模塊,每次創(chuàng)建項目都要自己去配置一下才可以,經常碼代碼使用起來有點嗎發(fā),但是使用這個 loguru 模塊,只需要兩行代碼即可完成以上配置,簡單易用。
安裝 pip install loguru
使用方法
最簡單的使用方法,只需要倒入模塊,然后 debug 輸出,看控制臺效果即可。 from loguru import logger logger.debug("That's it, beautiful and simple logging!")
打印在控制臺中是彩色的!
如果你的終端兼容,loguru 會自動為日志添加顏色。你可以通過使用接收器格式的標記標簽來定義自己喜歡的樣式。 logger.add(sys.stdout, colorize=True, format="{time} {message}")
輸出到文件中
只需要添加一行代碼即可 from loguru import logger # 添加到名為 demo.log 文件中 logger.add("demo.log") logger.debug("That's it, beautiful and simple logging!")
輸出到文件中
以時間為文件名分割日志,可以這樣做: from loguru import logger # 以時間分割日志 logger.add('file_{time}.log') logger.debug("That's it, beautiful and simple logging!")
效果展示(看文件名稱)
文件控制的高級用法 logger.add("rotation.log", rotation="500 MB")
以上配置可以實現(xiàn)每 500MB 存儲一個文件,每個 log 文件過大就會新創(chuàng)建一個 log 文件。我們在配置 log 名字時加上了一個 time 占位符,這樣在生成時可以自動將時間替換進去,生成一個文件名包含時間的 log 文件。
我們也可以使用 rotation 參數(shù)實現(xiàn)定時創(chuàng)建 log 文件,例如: logger.add('runtime_{time}.log', rotation='12:00')
這樣就是實現(xiàn)每天 12 點新創(chuàng)建一個 log 文件輸出了。
另外我們也可以配置 log 文件的循環(huán)時間,比如每隔兩周創(chuàng)建一個 log 文件,寫法如下: logger.add('runtime_{time}.log', rotation='2 week')
這樣我們就可以實現(xiàn)兩周創(chuàng)建一個 log 文件了。
不知道大家有沒有遇到過這樣的情況,很多情況下,一些非常久遠的 log 對我們來說并沒有什么用處了,它白白占據(jù)了一些存儲空間,不清除掉就會非常浪費。retention 這個參數(shù)可以配置日志的最長保留時間。
比如我們想要設置日志文件最長保留 7 天,可以這么來配置: logger.add('runtime.log', retention='7 days')
這樣 log 文件里面就會保留最新 7 天的 log,老師再也不用擔心 log 沉積的問題。
loguru 還可以配置文件的壓縮格式,比如使用 zip 文件格式保存,如下: logger.add('runtime.log', compression='zip')
這樣可以更加節(jié)省存儲空間。
字符串輸出 logger.info('If you are using Python {}, prefer {feature} of course!', 3.6, feature='f-strings')
這樣在添加參數(shù)就非常方便了。
Traceback 記錄
在很多情況下,如果遇到運行錯誤,而我們在打印輸出 log 的時候萬一不小心沒有配置好 Traceback 的輸出,很有可能我們就沒法追蹤錯誤所在了。
但用了 loguru 之后,我們用它提供的裝飾器就可以直接進行 Traceback 的記錄,類似這樣的配置即可: @logger.catch def my_function(x, y, z): # An error? It's caught anyway! return 1 / (x + y + z)
我們做個測試,我們在調用時三個參數(shù)都傳入 0,直接引發(fā)除以 0 的錯誤,看看會出現(xiàn)什么情況: my_function(0, 0, 0)
運行完畢之后,可以發(fā)現(xiàn) log 里面就出現(xiàn)了 Traceback 信息,而且給我們輸出了當時的變量值,真的是不能再贊了!結果如下: > File "run.py", line 15, in my_function(0, 0, 0) └ File "/private/var/py/logurutest/demo5.py", line 13, in my_function return 1 / (x + y + z) │ │ └ 0 │ └ 0 └ 0 ZeroDivisionError: division by zero
根據(jù)需要進行結構化日志記錄
希望對日志進行序列化以便于解析或傳遞日志?使用該 serialize 參數(shù),每條日志消息在發(fā)送到已配置的接收器之前將轉換為 JSON 字符串。 logger.add('file_{time}.log', serialize=True) # {"text": "2020-07-15 21:47:33.793 | DEBUG | __main__::14 - That's it, beautiful and simple logging!\n", "record": {"elapsed": {"repr": "0:00:00.017317", "seconds": 0.017317}, "exception": null, "extra": {}, "file": {"name": "loguru_demo.py", "path": "/Users/notes/modules/loguru_demo.py"}, "function": "", "level": {"icon": "??", "name": "DEBUG", "no": 10}, "line": 14, "message": "That's it, beautiful and simple logging!", "module": "loguru_demo", "name": "__main__", "process": {"id": 7280, "name": "MainProcess"}, "thread": {"id": 4458839488, "name": "MainThread"}, "time": {"repr": "2020-07-15 21:47:33.793271+08:00", "timestamp": 1594820853.793271}}}
郵件通知
Loguru 可以輕松地與功能強大的 notifiers 庫結合使用(必須單獨安裝),以在程序意外失敗時接收電子郵件或發(fā)送其他多種通知。 import notifiers params = { "username": " [email?protected] ", "password": "abc123", "to": " [email?protected] " } # Send a single notification notifier = notifiers.get_notifier("gmail") notifier.notify(message="The application is running!", **params) # Be alerted on each error message from notifiers.logging import NotificationHandler handler = NotificationHandler("gmail", defaults=params) logger.add(handler, level="ERROR")
或者配合 ES 使用
####~~比內置日志記錄快 10 倍~~ 盡管在大多數(shù)情況下,日志記錄對性能的影響可以忽略不計,但零成本的日志記錄器將允許在任何地方使用它而無需過多擔心。在即將發(fā)布的版本中,Loguru 的關鍵功能將以 C 語言實現(xiàn),以實現(xiàn)最大速度。
以上就是 loguru 的基本用法了,感興趣的小伙伴可以研究一下這個的用法,特別簡單易用,趕快去配置到你的項目中吧!
開源地址: https://github.com/Delgan/loguru
今天的推薦不知道大家喜歡嗎?如果你們喜歡話,請在文章底部留言或點贊,以表示對我的支持,你們的留言,點贊,轉發(fā)關注是我持續(xù)更新的動力哦!
關注公眾號回復:" 1024 ",免費領取一大波學習資源,先到先得哦!
https://flask.palletsprojects.com/en/master/api/#flask.Flask.run https://werkzeug.palletsprojects.com/en/master/serving/#werkzeug.serving.run_simple
threaded=True 開啟多線程 https://flask.palletsprojects.com/en/master/api/#url-route-registrations
@ app .route( 這里可以配置對某一個請求不開多線程嗎?
前提:爬取的是亞馬遜。爬蟲代碼不變,倆 virtualenv 都裝了一模一樣的包,在同一臺機子上,用同一個代理。其中一個環(huán)境一直出驗證碼和 503,但是切換到另外一個環(huán)境上卻都是正常響應。另外,使用抓包軟件看的話,一直出驗證碼的環(huán)境走抓包軟件代理后也會正常,但一不用就恢復原狀…… 使用了最簡單的 requests demo 也是一模一樣的情況 有沒有同學遇到過一樣的問題呢? 或者說有什么排查點呢? PS: 被反爬的環(huán)境是一直在運行爬蟲代碼的,目測可能是有機器學習機制,但是特征點完全找不到在哪,HTTP 層是一模一樣的,TCP 層粗略看了下也沒什么區(qū)別……
先說重點:子目錄也可能改名需求: 搜索一個目錄樹,匹配規(guī)則,符合的改名(包括文件名或目錄名) 規(guī)則匹配的對象是 Name,不是 Fullpath 開始想 scandir 并處理,但想想這樣不對,改了目錄名影響后續(xù) scan 如果先搜索一遍,然后按 fullpath 排序,倒序,再逐個處理,不確定這個思路對不對?
剛學兩天新手問 python 里的字典只能兩兩一組么?我想放三四五六七一組怎么辦? dic = {'甲':'A':1,'乙':'B':8,'丙':'C':3}
我根據(jù)指引文檔的例子創(chuàng)建了一個表使用以下的類,想讓表增加行時,當給 name 賦值中文字符串時出現(xiàn)類型出錯的提示,我想知道用什么類型才能支持中文。 class Particle(IsDescription): name = StringCol(itemsize=16) # 16-character string
分享一篇文章:
在 C/C++/Java 等等語言中,整型變量的自增或自減操作是標配,它們又可分為前綴操作(++i 和 --i )與后綴操作( i++ 和 i--),彼此存在著一些細微差別,各有不同的用途。
這些語言的使用者在接觸 Python 時,可能會疑惑為什么它不提供 ++ 或 -- 的操作呢?在我前不久發(fā)的《 Python 的十萬個為什么? 》里,就有不少同學在調查問卷中表示了對此話題感興趣。
Python 中雖然可能出現(xiàn) ++i 這種前綴形式的寫法,但是它并沒有“++”自增操作符,此處只是兩個“+”(正數(shù)符號)的疊加而已,至于后綴形式的“++”,則完全不支持( SyntaxError: invalid syntax )。
本期“ Python 為什么 ”欄目,我們將會從兩個主要的角度來回答: Python 為什么不支持 i++ 自增語法? ( PS:此處自增指代“自增和自減”,下同)
首先,Python 當然可以實現(xiàn)自增效果,即寫成 i += 1 或者 i = i + 1 ,這在其它語言中也是通用的。
雖然 Python 在底層用了不同的魔術方法( __add__() 和 __iadd__() )來完成計算,但表面上的效果完全相同。
所以,我們的問題可以轉化成: 為什么上面的兩種寫法會勝過 i++,成為 Python 的最終選擇呢?
1 、Python 的整數(shù)是不可變類型
當我們定義 i = 1000 時,不同語言會作出不同的處理: C 之類的語言(寫法 int i = 1000 )會申請一塊內存空間,并給它“綁定”一個固定的名稱 i,同時寫入一個可變的值 1000 。在這里,i 的地址以及類型是固定的,而值是可變的(在一定的表示范圍內) Python (寫法 i = 1000 )也會申請一塊內存空間,但是它會“綁定”給數(shù)字 1000,即這個 1000 的地址以及類型是固定的( immutable ),至于 i,只是一個名稱標簽貼在 1000 上,自身沒有固定的地址和類型
所以當我們令 i “自增”時( i = i + 1 ),它們的處理是不同的: C 之類的語言先找到 i 的地址上存的數(shù)值,然后令它加 1,操作后新的數(shù)值就取代了舊的數(shù)值 Python 的操作過程是把 i 指向的數(shù)字加 1,然后把結果綁定到新申請的一塊內存空間,再把名稱標簽 i “貼”到新的數(shù)字上。新舊數(shù)字可以同時存在,不是取代關系
打一個不太恰當?shù)谋确剑篊 中的 i 就像一個宿主,數(shù)字 1000 寄生在它上面;而 Python 中的 1000 像個宿主,名稱 i 寄生在它上面。C 中的 i 與 Python 中的 1000,它們則寄生在底層的內存空間上……
還可以這樣理解: C 中的變量 i 是一等公民,數(shù)字 1000 是它的一個可變的屬性; Python 中的數(shù)字 1000 是一等公民,名稱 i 是它的一個可變的屬性。
有了以上的鋪墊,我們再來看看 i++,不難發(fā)現(xiàn): C 之類的語言,i++ 可以表示 i 的數(shù)字屬性的增加, 它不會開辟新的內存空間,也不會產生新的一等公民 Python 之類的語言,i++ 如果是對其名稱屬性的操作,那樣就沒有意義了(總不能按字母表順序,把 i 變成 j 吧);如果理解成對數(shù)字本體的操作,那么情況就會變得復雜:它會產生新的一等公民 1001,因此需要給它分配一個內存地址,此時若占用 1000 的地址,則涉及舊對象的回收,那原有對于 1000 的引用關系都會受到影響,所以只能開辟新的內存空間給 1001
Python 若支持 i++,其操作過程要比 C 的 i++ 復雜,而且其含義也 不再是“令數(shù)字增加 1”(自增),而是“創(chuàng)建一個新的數(shù)字”(新增), 這樣的話,“自增操作符”( increment operator )就名不副實了。
Python 在理論上可以實現(xiàn) i++ 操作,但它就必須重新定義“自增操作符”,還會令有其它語言經驗的人產生誤解,不如就讓大家直接寫成 i += 1 或者 i = i + 1 好了。
2 、Python 有可迭代對象
C/C++ 等語言設計出 i++,最主要的目的是為了方便使用三段式的 for 結構: for(int i = 0; i < 100; i++){ // 執(zhí)行 xxx }
這種程序關心的是數(shù)字本身的自增過程,數(shù)字做加法與程序體的執(zhí)行相關聯(lián)。
Python 中沒有這種 for 結構的寫法,它提供了更為優(yōu)雅的方式: for i in range(100): # 執(zhí)行 xxx my_list = ["你好", "我是 Python 貓", "歡迎關注"] for info in my_list: print(info)
這里體現(xiàn)了不同的思維方式,它關心的是在一個數(shù)值范圍內的迭代遍歷,并不關心也不需要人為對數(shù)字做加法。
Python 中的可迭代對象 /迭代器 /生成器提供了非常良好的迭代 /遍歷用法,能夠做到對 i++ 的完全替代。
例如,上例中實現(xiàn)了對列表內值的遍歷,Python 還可以用 enumerate() 實現(xiàn)對下標與具體值的同時遍歷: my_list = ["你好", "我是 Python 貓", "歡迎關注"] for i, info in enumerate(my_list): print(i, info) # 打印結果: 0 你好 1 我是 Python 貓 2 歡迎關注
再例如對于字典的遍歷,Python 提供了 keys()、values()、items() 等遍歷方法,非常好用: my_dict = {'a': '1', 'b': '2', 'c': '3'} for key in my_dict.keys(): print(key) for key, value in my_dict.items(): print(key, value)
有了這樣的利器,哪里還有 i++ 的用武之地呢?
不僅如此,Python 中基本上很少使用 i += 1 或者 i = i + 1 ,由于存在著隨處可見的可迭代對象,開發(fā)者們很容易實現(xiàn)對一個數(shù)值區(qū)間的操作,也就很少有對于某個數(shù)值作累加的訴求了。
所以,回到我們開頭的問題,其實這兩種“自增”寫法并沒有勝出 i++ 多少,只因為它們是通用型操作,又不需要引入新的操作符,所以 Python 才延續(xù)了一種基礎性的支持。 真正的贏家其實是各種各樣的可迭代對象!
稍微小結下:Python 不支持自增操作符,一方面是因為它的整數(shù)是不可變類型的一等公民,自增操作(++)若要支持,則會帶來歧義;另一方面主要因為它有更合適的實現(xiàn),即可迭代對象,對遍歷操作有很好的支持。
如果你覺得本文分析得不錯,那你應該會喜歡這些文章:
1 、 Python 為什么使用縮進來劃分代碼塊?
2 、 Python 的縮進是不是反人類的設計?
3 、 Python 為什么不用分號作語句終止符?
4 、 Python 為什么沒有 main 函數(shù)?為什么我不推薦寫 main 函數(shù)?
5 、 Python 為什么推薦蛇形命名法?
6 、 Python 為什么不支持 i++ 自增語法,不提供 ++ 操作符
7 、 Python 為什么只需一條語句“a,b=b,a”,就能直接交換兩個變量?
寫在最后:本文屬于“Python 為什么”系列( Python 貓出品),該系列主要關注 Python 的語法、設計和發(fā)展等話題,以一個個“為什么”式的問題為切入點,試著展現(xiàn) Python 的迷人魅力。
分享一篇文章:
從接觸 Python 時起,我就覺得 Python 的元組解包( unpacking )挺有意思,非常簡潔好用。
最顯而易見的例子就是多重賦值,即在一條語句中同時給多個變量賦值: >>> x, y = 1, 2 >>> print(x, y) # 結果:1 2
在此例中,賦值操作符“=”號的右側的兩個數(shù)字會被存入到一個元組中,即變成 (1,2),然后再被解包,依次賦值給“=”號左側的兩個變量。
如果我們直接寫 x = 1,2 ,然后打印出 x,或者在“=”號右側寫成一個元組,就能證實到這一點: >>> x = 1, 2 >>> print(x) # 結果:(1, 2) >>> x, y = (1, 2) >>> print(x, y) # 結果:1 2
一些博客或公眾號文章在介紹到這個特性時,通常會順著舉一個例子,即基于兩個變量,直接交換它們的值: >>> x, y = 1, 2 >>> x, y = y, x >>> print(x, y) # 結果:2 1
一般而言,交換兩個變量的操作需要引入第三個變量。道理很簡單,如果要交換兩個杯子中所裝的水,自然會需要第三個容器作為中轉。
然而,Python 的寫法并不需要借助中間變量,它的形式就跟前面的解包賦值一樣。正因為這個形式相似,很多人就誤以為 Python 的變量交換操作也是基于解包操作。
但是,事實是否如此呢?
我搜索了一番,發(fā)現(xiàn)有人試圖回答過這個問題,但是他們的回答基本不夠全面。(當然,有不少是錯誤的答案,還有更多人只是知其然,卻從未想過要知其所以然)
先把本文的答案放出來吧: Python 的交換變量操作不完全基于解包操作,有時候是,有時候不是!
有沒有覺得這個答案很神奇呢?是不是聞所未聞?!
到底怎么回事呢?先來看看標題中最簡單的兩個變量的情況,我們上 dis 大殺器看看編譯的字節(jié)碼:
上圖開了兩個窗口,可以方便比較“a,b=b,a”與“a,b=1,2”的不同: “a,b=b,a”操作:兩個 LOAD_FAST 是從局部作用域中讀取變量的引用,并存入棧中,接著是最關鍵的 ROT_TWO 操作,它會交換兩個變量的引用值,然后兩個 STORE_FAST 是將棧中的變量寫入局部作用域中。 “a,b=1,2”操作:第一步 LOAD_CONST 把“=”號右側的兩個數(shù)字作為元組放到棧中,第二步 UNPACK_SEQUENCE 是序列解包,接著把解包結果寫入局部作用域的變量上。
很明顯,形式相似的兩種寫法實際上完成的操作并不相同。在交換變量的操作中,并沒有裝包和解包的步驟!
ROT_TWO 指令是 CPython 解釋器實現(xiàn)的對于棧頂兩個元素的快捷操作,改變它們指向的引用對象。
還有兩個類似的指令是 ROT_THREE 和 ROT_FOUR,分別是快捷交換三和四個變量(摘自:ceval.c 文件,最新的 3.9 分支):
預定義的棧頂操作如下:
查看官方文檔中對于這幾個指令的解釋,其中 ROT_FOUR 是 3.8 版本新加的: ROT_TWO
Swaps the two top-most stack items. ROT_THREE
Lifts second and third stack item one position up, moves top down to position three. ROT_FOUR
Lifts second, third and forth stack items one position up, moves top down to position four. New in version 3.8.
CPython 應該是以為這幾種變量的交換操作很常見,因此才提供了專門的優(yōu)化指令。就像 [-5,256] 這些小整數(shù)被預先放到了整數(shù)池里一樣。
對于更多變量的交換操作,實際上則會用到前面說的解包操作:
截圖中的 BUILD_TUPLE 指令會將給定數(shù)量的棧頂元素創(chuàng)建成元組,然后被 UNPACK_SEQUENCE 指令解包,再依次賦值。
值得一提的是,此處之所以比前面的“a,b=1,2”多出一個 build 操作,是因為每個變量的 LOAD_FAST 需要先單獨入棧,無法直接被組合成 LOAD_CONST 入棧。也就是說,“=”號右側有變量時,不會出現(xiàn)前文中的 LOAD_CONST 一個元組的情況。
最后還有一個值得一提的細節(jié),那幾個指令是跟棧中元素的數(shù)量有關,而不是跟賦值語句中實際交換的變量數(shù)有關??匆粋€例子就明白了:
分析至此,你應該明白前文中的結論是怎么回事了吧?
我們稍微總結一下: Python 能在一條語句中實現(xiàn)多重賦值,這是利用了序列解包的特性 Python 能在一條語句中實現(xiàn)變量交換,不需引入中間變量,在變量數(shù)少于 4 個時( 3.8 版本起是少于 5 個),CPython 是利用了 ROT_* 指令來交換棧中的元素,當變量數(shù)超出時,則是利用了序列解包的特性。 序列解包是 Python 的一大特性,但是在本文的例子中,CPython 解釋器在小小的操作中還提供了幾個優(yōu)化的指令,這絕對會超出大多數(shù)人的認知
如果你覺得本文分析得不錯,那你應該會喜歡這些文章:
1 、 Python 為什么使用縮進來劃分代碼塊?
2 、 Python 的縮進是不是反人類的設計?
3 、 Python 為什么不用分號作語句終止符?
4 、 Python 為什么沒有 main 函數(shù)?為什么我不推薦寫 main 函數(shù)?
5 、 Python 為什么推薦蛇形命名法?
6 、 Python 為什么不支持 i++ 自增語法,不提供 ++ 操作符?
寫在最后:本文屬于“Python 為什么”系列( Python 貓出品),該系列主要關注 Python 的語法、設計和發(fā)展等話題,以一個個“為什么”式的問題為切入點,試著展現(xiàn) Python 的迷人魅力。
今天在做動態(tài)規(guī)劃的時候創(chuàng)建二維列表的時候發(fā)現(xiàn)了一個疑問, 代碼如下 def func(N, total_weight): weight = [1, 2, 3, 4] value = [2, 4, 4, 5] dp = [[0 for i in range(total_weight+1)] for j in range(N+1)] print(dp) # dp = [[0] * (total_weight + 1)] * (N+1) # print(dp) for i in range(1, N + 1): for j in range(1, total_weight + 1): if j >= weight[i - 1]: value1 = dp[i - 1][j - weight[i - 1]] + value[i - 1] dp[i][j] = max(value1, dp[i - 1][j]) else: dp[i][j] = dp[i - 1][j] return dp func(4, 6)
dp = [[0 for i in range(total_weight+1)] for j in range(N+1)] 創(chuàng)建的列表和 dp = [[0] * (total_weight + 1)] * (N+1)創(chuàng)建的列表完全相同, 但是最后兩者得到的結果完全不同, 前者使用 for 循環(huán)得到的結果最后是正確的, 為什么會這樣呢???
for 循環(huán)得到的列表值: [[0, 0, 0, 0, 0, 0, 0], [0, 2, 2, 2, 2, 2, 2], [0, 2, 4, 6, 6, 6, 6], [0, 2, 4, 6, 6, 8, 10], [0, 2, 4, 6, 6, 8, 10]]
直接乘號得到的列表值: [[0, 2, 4, 6, 8, 10, 12], [0, 2, 4, 6, 8, 10, 12], [0, 2, 4, 6, 8, 10, 12], [0, 2, 4, 6, 8, 10, 12], [0, 2, 4, 6, 8, 10, 12]]
hello,小伙伴們,大家好,今天給大家分享的開源項目是: proxy_pool ,這個開源項目是抓取個大免費代理 IP 網(wǎng)站,感興趣的爬蟲可以嘗試把代碼 clone 下載然后嘗試應用一下,加油?。。?______ ______ _ | ___ \_ | ___ \ | | | |_/ / \__ __ __ _ __ _ | |_/ /___ ___ | | | __/| _// _ \ \ \/ /| | | || __// _ \ / _ \ | | | | | | | (_) | > < \ |_| || | | (_) | (_) || |___ \_| |_| \___/ /_/\_\ \__ |\_| \___/ \___/ \_____\ __ / / /___ /
免費代理源
目前實現(xiàn)的采集免費代理網(wǎng)站有(排名不分先后, 下面僅是對其發(fā)布的免費代理情況, 付費代理測評可以參考 這里 ):
如果還有其他好的免費代理網(wǎng)站, 可以在提交在 issues , 下次更新時會考慮在項目中支持。
運行項目
下載代碼: git clone [email?protected] :jhao104/proxy_pool.git
or https://github.com/jhao104/proxy_pool/releases 下載對應 zip 文件
安裝依賴: pip install -r requirements.txt
更新配置: # setting.py 為項目配置文件 # 配置 API 服務 HOST = "0.0.0.0" # IP PORT = 5000 # 監(jiān)聽端口 # 配置數(shù)據(jù)庫 DB_CONN = 'redis://@127.0.0.1:8888' # 配置 ProxyFetcher PROXY_FETCHER = [ "freeProxy01", # 這里是啟用的代理抓取方法名,所有 fetch 方法位于 fetcher/proxyFetcher.py "freeProxy02", # .... ]
啟動項目: # 如果已經具備運行條件, 可用通過 proxyPool.py 啟動。 # 程序分為: schedule 調度程序 和 server Api 服務 # 啟動調度程序 python proxyPool.py schedule # 啟動 webApi 服務 python proxyPool.py server
Docker 運行 docker pull jhao104/proxy_pool docker run --env DB_CONN=redis://: [email?protected] :port/db -p 5010:5010 jhao104/proxy_pool:2.1.0
使用
如果要在爬蟲代碼中使用的話, 可以將此 api 封裝成函數(shù)直接使用,例如: import requests def get_proxy(): return requests.get("http://127.0.0.1:5010/get/").json() def delete_proxy(proxy): requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy)) # your spider code def getHtml(): # .... retry_count = 5 proxy = get_proxy().get("proxy") while retry_count > 0: try: html = requests.get('http://www.example.com', proxies={"http": "http://{}".format(proxy)}) # 使用代理訪問 return html except Exception: retry_count -= 1 # 刪除代理池中代理 delete_proxy(proxy) return None
擴展代理
項目默認包含幾個免費的代理獲取源,但是免費的畢竟質量有限,所以如果直接運行可能拿到的代理質量不理想。所以,提供了代理獲取的擴展方法。
添加一個新的代理源方法如下: 1 、首先在 ProxyFetcher 類中添加自定義的獲取代理的靜態(tài)方法, 該方法需要以生成器(yield)形式返回 host:ip 格式的代理,例如: class ProxyFetcher(object): # .... # 自定義代理源獲取方法 @staticmethod def freeProxyCustom1(): # 命名不和已有重復即可 # 通過某網(wǎng)站或者某接口或某數(shù)據(jù)庫獲取代理 # 假設你已經拿到了一個代理列表 proxies = ["x.x.x.x:3128", "x.x.x.x:80"] for proxy in proxies: yield proxy # 確保每個 proxy 都是 host:ip 正確的格式返回
2 、添加好方法后,修改 setting.py 文件中的 PROXY_FETCHER 項: 在 PROXY_FETCHER 下添加自定義方法的名字: PROXY_FETCHER = [ "freeProxy01", "freeProxy02", # .... "freeProxyCustom1" # # 確保名字和你添加方法名字一致 ]
schedule 進程會每隔一段時間抓取一次代理,下次抓取時會自動識別調用你定義的方法。
以上就是這個開源項目的詳細介紹了,感興趣的小伙伴可以嘗試應用一下。
開源地址: https://github.com/jhao104/proxy_pool
今天的推薦不知道大家喜歡嗎?如果你們喜歡話,請在文章底部留言或點贊,以表示對我的支持,你們的留言,點贊,轉發(fā)關注是我持續(xù)更新的動力哦!
關注公眾號回復:" 1024 ",免費領取一大波學習資源,先到先得哦!
借用官網(wǎng)例子說明我的疑問: with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): ...
官網(wǎng)的例子都是這樣,將所有任務一次性放到 executor 后才使用 as_completed 判斷。
如果我需要從隊列中不斷取任務的話,該怎么使用 as_completed 比較合適呢? # 類似于這個意思 while True: executor.submit(load_url) time.sleep(1) while True: for future in concurrent.futures.as_completed(): #do sth...
使用兩個線程?感覺在套娃……
或者說 ThreadPoolExecutor 不適用于該場景,需要自己寫 threading 方法?
有個 scrapy 項目整體流程大概是: spider.start_requests 從 redis 的 tasks_keys 里獲取 url middleware.proxyMiddleware.process_request 從 redis 的 proxy_keys 里獲取代理 spider.parse 解析出 item,需深度抓取的 url,深度抓取 url 放入 redis 的 tasks_keys 里 pipelines.MyItem 把解析出的 item 存入 redis 的 item_keys 里面 。。。。 總結來說,有 4 個地方需要用到同一個 redis 數(shù)據(jù)庫,區(qū)別只在 key 目前的寫法是, middleware.proxyMiddleware 里面__init__聲明了 redis.ConnectionPool 連接池,以及 redis.StrictRedis 連接 在 pipelines.MyItem 和 spider 繼承的類__init__里面全部粘貼復制了一遍。。。 一模一樣的代碼寫了三個地方 雖然程序可以正常跑,但是,這方法越看越覺得傻 有什么方法可以只聲明一個 redis 鏈接,然后在 spider 、middleware 、pipeline 復用同一個鏈接嗎? 搜了一圈,各種出錯,沒有實際進展
hello,小伙伴們大家好,今天給大家推薦的開源項目是 : CxSpider ,這個開源整合了作者自己的采集過的所有產品,包括微博、Twitter 、玩加、知網(wǎng)、虎牙、斗魚、B 站、WeGame 、貓眼、豆瓣、安居客、居理新房感興趣的小伙伴可以下載看看,應該可以給你提供一個可借鑒的思路。
Project
爬蟲詳情
1. Twitter 用戶信息爬蟲(twitter.user_info) @ author ChangXing @ version 4.1 @ create 2017.12.25 @ revise 2020.06.08
使用第三方模塊 twitter-scraper 采集 Twitter 用戶信息;因為該模塊采集的粉絲數(shù)和關注數(shù)可能存在偏差,因此再通過 Selenium 抓取 Twitter 用戶信息,以更正該模塊采集的數(shù)量。 采集信息:粉絲數(shù)和關注數(shù)為 twitter-scraper 采集并配合 Selenium 爬蟲檢查,其他字段為 twitter-scraper 采集。 應用配置:無需使用代理 IP,需要使用 Selenium
2. Twitter 用戶推文爬蟲(twitter.user_tweet) @ author ChangXing @ version 4.0 @ create 2017.12.30 @ revise 2020.06.08
微博熱搜榜實時爬蟲(weibo.hot_ranking) @ author ChangXing @ Version 1.1 @ create 2020.05.29 @ revise 2020.06.08
定時采集微博熱搜榜。 采集信息:每 5 分鐘采集 1 次,每次約 50 條記錄→每天約 14400 條記錄 數(shù)據(jù)清洗:熱搜榜置頂熱搜(固定第 1 條)和廣告熱搜(標注推薦) 應用配置:無需使用代理 IP 、無需使用 Selenium
環(huán)境變量
爬蟲功能的正常使用需要配置如下環(huán)境變量,可以直接修改 environment.py 中的環(huán)境變量值,也可以修改配置 Json 文件。
環(huán)境配置
Python/Pip 環(huán)境 Python >= 3.8.0 requests >= 2.23.0 idna >= 2.9 urllib3 >= 1.25.9 certifi >= 2020.4.5.1 chardet >= 3.0.4 bs4 >= 0.0.1 beautifulsoup4 >= 4.9.0 soupsieve >= 2.0 apscheduler >= 3.6.3 pytz >= 2019.3 six >= 1.14.0 tzlocal >= 2.1 setuptools mysql-connector >= 2.2.9 lxml >= 4.5.0 selenium >= 3.141.0 (用于 Selenium 爬蟲) urllib3 >= 1.25.9 twitter-scraper >= 0.4.1 (用于 Twitter 用戶信息爬蟲) requests-html >= 0.10.0 MachanicalSoup >= 0.12.0
開源地址: https://github.com/ChangxingJiang/CxSpider
今天的推薦不知道大家喜歡嗎?如果你們喜歡話,請在文章底部留言或點贊,以表示對我的支持,你們的留言,點贊,轉發(fā)關注是我持續(xù)更新的動力哦!
關注公眾號回復:" 1024 ",免費領取一大波學習資源,先到先得哦!
1 、win10 里面如何寫爬蟲的定時任務?沒想過定時任務這塊不太懂 2 、每次爬取出來的數(shù)據(jù),有重復的,用的是 mysql 數(shù)據(jù)庫,如何更好的解決這個問題? 暫時想到的兩個方法,一個是定時清除重復數(shù)據(jù),另外一種是顯示最新的那條數(shù)據(jù)
如題,使用 python 編寫了個發(fā)送郵件的 Demo 。郵件發(fā)送后,用 Foxmail 能夠正常收的到。
但是收件人一欄顯示的收件郵箱很奇怪,如下圖,一整個收件郵箱被按字符拆分為好多個小郵箱,小郵箱的那域名我也沒見過。
原本收件郵箱應該顯示是 [email?protected]
不知道有大佬遇到過這種情況沒,請教下
下面是源碼(看著沒毛?。?# 編譯日期:2019-10-14 15:01:36 # coding=utf-8 import os from email.mime.text import MIMEText from email.header import Header from email.mime.multipart import MIMEMultipart from email.mime.application import MIMEApplication # 發(fā)送郵件(附件) # email_user: 發(fā)件人 # email_pass: 密碼 # receivers:收件人列表,例:[' [email?protected] ',' [email?protected] '] # filepath: 文件地址 如:r'D:\分行查詢支行卷別庫存 Excel\作文.xlsx' def sendEmail(email_user, email_pass, receivers, filepath): mail_host = '10.10.10.10' # 設置服務器地址 sender = email_user + '@xxx.com.cn' # 發(fā)件人郵箱 # 創(chuàng)建一個帶附件的實例 message = MIMEMultipart() # 設置發(fā)件人、收件人 message['From'] = sender message['To'] = ", ".join(receivers) # 設置郵件主題 message['Subject'] = Header('查凍扣報備文件', 'utf-8') # 郵件正文 message.attach(MIMEText('查凍扣報備文件已發(fā)送,請查看附件!', 'plain', 'utf-8')) # 構造附件 xlsx = MIMEApplication(open(filepath,'rb').read()) xlsx['Content-Type'] = 'application/octet-stream' filename = os.path.basename(filepath) xlsx.add_header('Content-Disposition', 'attachment', filename=Header(filename, 'utf-8').encode()) message.attach(xlsx) try: smtpObj = smtplib.SMTP(mail_host, 1025) smtpObj.login(email_user, email_pass) smtpObj.sendmail(sender, receivers, message.as_string()) print("郵件發(fā)送成功,收件人:" + str(receivers) + "\n 附件地址:" + str(filepath)) except smtplib.SMTPException as e: print("郵件發(fā)送失敗,收件人:" + str(receivers) + "\n 附件地址:" + str(filepath)) print(e)