前言
最近想從圖書館裡借一本書,可是圖書館裡那兩本書都借走了,其中有一本書在3月3號到期應還,所以我想著這幾天那個人應該會來圖書館還書,所以我寫了個python指令碼,放在伺服器上,每隔一段時間查詢,如果那人還書了,郵件通知我。這樣我就可以及時借書了,哈哈。
使用的工具:
谷歌瀏覽器;Python3.8 ,雲linux伺服器
所需知識:
瀏覽器開發者工具的基本使用;http get請求;json處理;smtp郵件傳送;linux伺服器crontab的使用
分析web頁面
判斷資料載入方式
找到需要分析的web頁面,開啟瀏覽器的開發者工具,重新整理。
這是我學校圖書館網址:圖書館書籍查詢
上圖展示的是我要查詢的書(《tensorflow從零開始學》),第二個標註的是書的存在狀態。
頁面有了,於是開始分析這些資訊是怎麼來的。
幸運的是,書的存在狀態是網頁透過AJAX獲取的json來載入資訊。下一標題會展示我是怎麼找資料的。分析json資訊即可得到所需資料(因為資料是後來載入的,可以先把網頁下載下來,看看有沒有資訊,沒有的話,就是後期js獲取的)
如果伺服器直接返回的頁面直接包含所需資料,那就比較麻煩了,需要分析html頁面,不過也簡單,以前用java的jsoup工具分析html比較好用,Python應該也有處理html的庫,初學python,不大熟悉。
迴歸正題
js獲取的內容可以在谷歌瀏覽器的開發者面板裡,找到Network,再選擇XHR。如下圖
列表裡展示的是這個頁面所有的js請求
分析js請求
透過枯燥乏味的尋找(一定要耐心尋找,這是最耗時間的地方),我終於找到一個請求,裡面是json資訊,如下圖
可以看到第四個js請求中返回的是json資料,json資料中有我需要的資訊
分析http請求
切換到header選項,如下圖
你會發現請求方式為Get請求,引數為如下圖所示
一看就知道bookrecnos為請求書目的id,想查什麼數目就加上數目id引數
然後返回的是json格式資料,我把json資料複製到csdn的json解析工具裡(什麼json解析工具無所謂。我只是為了方便看json資訊,我用的是CSDN外掛中json工具,使用方便一些),如下圖
左側為原本資料,右側為json工具處理的,是不是清爽了許多?
分析json資料
可以看到key為previews裡面有書籍資訊,我們要查詢的數目id為1901457577
1901457577裡面有多組資訊,因為我們學校有多個校區,所以展示的是多個校區的查詢結果,我們只要青島校區的資料,資料如下:
"1901445771":
{
"bookrecno": 1901445771,
"callno": "TP183/147",
"curlib": "01000",
"curlibName": "青島校區",
"curlocal": "QZKK",
"curlocalName": "青島自科書庫",
"copycount": 2,
"loanableCount": 0,
"shelfno": null,
"barcode": "4634944"
},
copycount為總共的書的存量
loanableCount為剩餘書的存量
現在已經知道json的資料存放位置,下面開始進行寫python指令碼
編寫Python指令碼
我自學的第一門語言是java,其實java也可以,但是由於在學深度學習,現在以後主要學習python,所以這次我嘗試使用Python工具來編寫指令碼
匯入需要的庫
import requests
import json
import smtplib
import datetime
from email.mime.text import MIMEText
from email.header import Header
這些庫都是平常使用的,requests庫用來發送get請求,json庫來解析json資料,smtplib來進行資料傳送。email路用來編寫郵件內容
傳送get請求
#要查詢的數目id
id=["1901457577"]#可以為多個數目,我只想查詢一個書
#引數params為字典型別,“bookrecnos”為查詢的數目id,想查詢多個數目的話,以逗號隔開(這裡只想查詢一個書)
params={"bookrecnos":id,"return_fmt":"json"}
response=requests.get("http://interlib.sdust.edu.cn/opac/book/holdingPreviews",params=params)
使用requests.get()傳送get請求
解析json
使用json.loads()方法返回的是字典,
JSON 解碼為 Python 型別轉換對應表:
json=json.loads(response.text)
#previews是字典,裡面key為剛才查詢引數帶的書的id
preview=json["previews"]
#要id為1901457577的數目
book_info=preview[id[0]]
#從book_info列表中挑選含有“青島校區”的字典
book={}
for i in book_info:
school=i["curlibName"]
if school== "青島校區":
book=i
break #如果找到 青島校區,直接跳出迴圈
count=book["copycount"]#共有幾本書
remainCount=book["loanableCount"]#剩餘幾本書
smtp傳送郵件
我用的163郵箱傳送到我的qq郵箱,
你需要在163郵箱中申請一個授權碼,獲取授權碼的方式可以百度一下,這裡不做敘述
#如果有書,則傳送郵件通知我
if count>0 and remainCount==0:
message="id為{0}的書,現有{1}本,總共有{2}本,當前時間:{3}".format(id[0],remainCount,count,datetime.datetime.now())
print(message)
# 第三方 SMTP 服務
mail_host="smtp.163.com" #設定伺服器
mail_user="[email protected]" #使用者名稱,你想使用什麼郵箱傳送資訊
mail_pass="XXXXXXXXXXX" #口令,郵箱授權碼
sender = '[email protected]'
receivers = ['[email protected]'] # 接收郵件,可設定為你的QQ郵箱或者其他郵箱
mess = MIMEText(message, 'plain', 'utf-8')
subject = "圖書查詢結果"
mess['Subject'] = Header(subject, 'utf-8')
mess['From'] = sender
mess['To'] =receivers[0]
smtp = smtplib.SMTP_SSL(mail_host, 994)
try:
smtp.login(mail_user,mail_pass)
smtp.sendmail(sender, receivers, mess.as_string())
print ("郵件傳送成功")
except smtplib.SMTPException as e:
print ("Error: 無法傳送郵件")
print(e)
finally :
smtp.close
else:
print("沒有剩餘的書了")
print("程式執行完成...")
注意:
from 和to一定要這麼寫:
mess['From'] = sender
mess['To'] =receivers[0]
1
2
不然會被163判斷為垃圾郵件,發不出去。
使用SMTP_SSL
smtp = smtplib.SMTP_SSL(mail_host, 994)
1
其實本來我寫的是smtp = smtplib.SMTP(mail_host, 25)
windows下編寫的時候能用,但是我放到伺服器執行不能用,可能是伺服器埠的問題吧。使用SMTP_SSL()萬無一失。
這是我寫的指令碼檔案,可以下載。
bookSearch.py
雲伺服器執行
將.py檔案上傳至伺服器
設定linux中crontab定時任務
使用crontab -e來編輯定時任務
crontab -e
1
*/10 8-22 * * * python3 /data/python_proj/library/bookSearch.py
1
我設定的是8點至22點,每10分鐘發查詢一次
crontab的具體使用可以參考這篇文章:Linux crontab命令的使用方法
然後重啟crontab服務就可以了
總結