1.綜述
偽代碼 可以參考《廿-爬URL以及分詞情緒分析初步設(shè)想》,才發(fā)現(xiàn)這個(gè)要做一整天才做得出來,不過大部分時(shí)間都是用來 部署 服務(wù)器。
代碼放在大型同性交友網(wǎng)站
其實(shí)根據(jù) 偽代碼 來寫程序很簡(jiǎn)單,但主要有很多地方卡住,需要現(xiàn)學(xué)現(xiàn)賣,以下均為現(xiàn)學(xué)的點(diǎn)。
2.關(guān)鍵技術(shù)點(diǎn)
2.1 Python Class
關(guān)于 Python 的 類,對(duì)于其他 腳本語言 的類來說并無太大差異,但不知道是不是習(xí)慣了 JS 的閉包,寫到 Python 上就會(huì)很多莫名其妙的錯(cuò)誤。
而且其實(shí)本次并無 繼承 方面的需求,所以純粹是為了寫 類 而寫。
2.2 異步
異步 這東西用在 Python 上面簡(jiǎn)直是崩潰,所以我不懂為什么那么多人喜歡 Python(還是因?yàn)樗翘焐?同步 的所以才那么多人喜歡么?還是純粹是因?yàn)樗泻芏喟浚?br>
Python 異步比較多的是 asyncio 。
關(guān)于 asyncio ,我覺得最絕望的是,根本不知道怎么 列隊(duì)!就是如何啟動(dòng),我嘗試過兩種辦法:
# --------- 以下不懂,失敗嘗試-------------
class classSpy():
def __init__(self, arrInProxy):
self.arrProxy = iter(arrInProxy)
def __aiter__(self):
return self
async def __anext__(self):
try:
eleProxy = next(self.arrProxy)
except StopIteration:
raise StopAsyncIteration
return eleProxy
arrTmp = []
arrTmp.append(1)
arrTmp.append(2)
arrTmp.append(3)
arrTmp.append(4)
arrTmp.append(5)
arrTmp.append(6)
async def run():
print('Begin : '+time.strftime('%Y-%m-%d %H:%M:%S'))
async for eleBe in classSpy(arrTmp):
await asyncio.sleep(random.randint(1, 3))
print(' Now : ' + str(eleBe) + ' , time: ' +
time.strftime('%Y-%m-%d %H:%M:%S'))
print('End : '+time.strftime('%Y-%m-%d %H:%M:%S'))
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
# ------------------------------------------
# --------- 以下為異步嘗試成功-------------
arrTmp = []
arrTmp.append(1)
arrTmp.append(2)
arrTmp.append(3)
arrTmp.append(4)
arrTmp.append(5)
arrTmp.append(6)
async def run(eleBe, inSemaphore):
async with inSemaphore:
await asyncio.sleep(random.randint(1, 3))
print(' Now : ' + str(eleBe) + ' , time: ' +
time.strftime('%Y-%m-%d %H:%M:%S'))
def funDone(waittask):
print('Callback End : '+time.strftime('%Y-%m-%d %H:%M:%S'))
print('Begin : '+time.strftime('%Y-%m-%d %H:%M:%S'))
# -------------調(diào)用方式1----------------
async def main():
semaphore = asyncio.Semaphore(2)
waittask = asyncio.gather(*([run(proxy, semaphore) for proxy in arrTmp]))
waittask.add_done_callback(funDone)
await asyncio.gather(waittask)
asyncio.run(main())
# -------------------------------------
# -------------調(diào)用方式2----------------
loop = asyncio.get_event_loop()
semaphore = asyncio.Semaphore(2)
waittask = asyncio.gather(*([run(proxy, semaphore) for proxy in arrTmp]))
waittask.add_done_callback(funDone)
loop.run_until_complete(waittask)
loop.close()
# -------------------------------------
print('Program End : '+time.strftime('%Y-%m-%d %H:%M:%S'))
# ------------------------------------------
其中我嘗試了很久,然后最終還是得去參考官方文檔。參考的文檔如下:
很艱難終于能 啟動(dòng) 真正的 異步 處理了,如上述方法2,但是在 多線程異步 的時(shí)候,發(fā)現(xiàn) Loop 在同一程序中不支持 同時(shí)多次調(diào)用,找了好久終于找到以下方法:
2.2 Python 鏈接 MongoDB
這個(gè)真是一個(gè)大坑,例如
-
find()函數(shù) 在Python中還是find() -
findOne()函數(shù)在Python中就是find_one() -
deleteMany()函數(shù)在Python中就是delete_many() - 因?yàn)?
Python沒有JSON,所以只能用字典,如:{$lt:10} 要寫成 {'$lt':10}
參考資料有:
某個(gè)資料
2.3 網(wǎng)頁請(qǐng)求及解析
這個(gè)倒比較方便,直接用人家寫好的就行了,參考資料如下:
別人的資料
2.4 超時(shí)重復(fù)請(qǐng)求
當(dāng)有當(dāng)前引用的代理 超時(shí) 的時(shí)候,請(qǐng)求另外的 代理服務(wù)器,但好像沒有特定的處理辦法,所以只有參考材料,做一個(gè) While 做判斷是否超時(shí),相關(guān)代碼如參考文章:
參考文章
3.部署Python程序
這個(gè)是真的是一個(gè)巨坑,我都不想弄了,但沒辦法,都已經(jīng)開始了。
NodeJS 我是用 PM2 的,PM2 其實(shí)也有一些坑,例如在 Start 一個(gè)項(xiàng)目后,需要 Save 再 Startup 以達(dá)到 開機(jī)啟動(dòng) 的環(huán)境,但是中間需要配置一個(gè) 環(huán)境配置,不然開機(jī)后仍然無法啟動(dòng)。
而 Python 的程序管理軟件有一個(gè) Supervisord ,從很久之前就在用這個(gè),可是重新配置還是很麻煩的。
3.1 關(guān)于安裝
在裝這個(gè)軟件時(shí),我發(fā)現(xiàn) 騰訊云 服務(wù)器是沒有預(yù)裝 Pip 的,裝完 Pip 之后再裝 Supervisord 發(fā)現(xiàn)很多東西根本沒有配置,直到找到這個(gè)文章:
centos7安裝supervisor詳細(xì)教程
可是我已經(jīng)裝好了,用了一個(gè)不推薦的方法,唉。
3.2 關(guān)于配置
沒關(guān)系,裝好之后,為什么 配置 那么麻煩。因?yàn)槲沂窍肟纯次业某绦蜉敵觯员仨毎?托管程序 的輸出 輸出 到某個(gè)目錄下,配置好麻煩,以下是主要能實(shí)施我功能的配置。
配置介紹
[program:spylink]
command=python3 /home/Berry/Repositories/SpyTheLink/run.py ; 這個(gè)就是我的路徑了,因?yàn)槲矣?Python3 寫的,所以這個(gè)比較重要
directory=/home/Berry/Repositories/SpyTheLink ; directory to cwd to before exec (def no cwd),這個(gè)需要配置,不然配置文件找不到路徑
autostart=true ; start at supervisord start (default: true) ,這個(gè)是當(dāng)然的
startsecs=10 ; number of secs prog must stay running (def. 1)
autorestart=true ; whether/when to restart (default: unexpected)
startretries=0 ; max # of serial start failures (default 3)
user=Berry ; setuid to this UNIX account to run the program,用Root不能運(yùn)行我也不知道為什么,好像沒設(shè)可運(yùn)行?還是運(yùn)行環(huán)境問題?
priority=999 ; the relative start priority (default 999)
redirect_stderr=false ; redirect proc stderr to stdout (default false),因?yàn)槲也恍枰磗tderr的,主要看輸出結(jié)果(錯(cuò)是很正常的這種趕出來的程序)
stdout_logfile_maxbytes=10MB ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups = 10 ; # of stdout logfile backups (default 10)
stdout_logfile=/home/Berry/Repositories/SpyTheLink/logs/spylink.out
stderr_logfile=/home/Berry/Repositories/SpyTheLink/logs/spylink.err ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=10MB ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10 ; # of stderr logfile backups (default 10)
loglevel=info ;(log level;default info; others: debug,warn,trace),因?yàn)槲沂切枰敵鲂畔?,所以不需要其他,默認(rèn)就好
4.后記
需要做一個(gè)以 Django 做為服務(wù)器端的人工判斷器并記錄,我可能需要再思考一下我該怎么做下一步先。