當前位置:
首頁 > 知識 > 我用 Python 和 Twilio 實現自動化選課

我用 Python 和 Twilio 實現自動化選課

(點擊

上方藍字

,快速關注我們)




編譯:伯樂在線 - 飛哥的咖啡


如有好文章投稿,請點擊 → 這裡了解詳情




大學生都知道那種選課時無課可選的痛苦,而我所在的大學甚至對大部分課程都不提供候補系統。我們每天不得不多次登錄查看選課網站。這種機械操作似乎是計算機擅長的事,所以我著手用一些學過的 Python 知識和 Twilio API 來實現選課自動化。






開始階段




由於大學的課程註冊系統需要密碼登錄,我們打算使用自建的簡化版網站(http://courses.project.samueltaylor.org/)。出於演示的目的,CS 101 課程的空餘名額將以 1 分鐘 1 次的頻率在 0 和 1 之間切換。




本項目中我們打算使用一些庫來幫助我們。假設你已經安裝了 pip,使用下面的 pip 命令來安裝需要的庫:





pip install requests==2.17.3 beautifulsoup4==4.6.0 redis==2.10.5 twilio==6.3.0 Flask==0.12.2



隨著項目的深入,我們會仔細研究用到的每一個庫。




抓取註冊系統




我們需要寫一個程序來幫助我們確定指定的課程是否有空餘名額。這裡我們使用網頁抓取技術來實現,它將從網路上下載網頁並尋找到重要的欄位(課程名額)。Requests 和 BeautifulSoup 是簡化這個過程的兩個非常流行的庫:Requests 讓獲取網頁變得更加簡單,而 BeautifulSoup 幫我們找到網頁中我們需要的部分。





# scraper.py

import

requests


from

bs4

import

BeautifulSoup



URL

=

"http://courses.project.samueltaylor.org/"

COURSE_NUM_NDX

=

0


SEATS_NDX

=

1


def

get_open_seats

()

:


r

=

requests

.

get

(

URL

)

soup

=

BeautifulSoup

(

r

.

text

,

"html.parser"

)


courses

=

{}



for

row

in

soup

.

find_all

(

"tr"

)

:


cols

=

[

e

.

text

for

e

in

row

.

find_all

(

"td"

)]


if

cols

:


courses

[

cols

[

COURSE_NUM_NDX

]]

=

int

(

cols

[

SEATS_NDX

])


return

courses




這裡的關鍵是 get_open_seats 函數。此函數中,我們使用 requests.get 下載網頁的 HTML 源碼,然後使用 BeautifulSoup 解析它。我們使用 find_all(『tr』) 獲得表內的所有行,通過更新課程詞典以顯示指定課程的剩餘名額。find_all 具有極其強大的功能,如果你對它感興趣並想要深入了解,你可以查看官方文檔。最後,我們返回課程詞典,這樣程序就能看到指定課程還有多少空餘名額(比如,courses[『CS 101』]是 CS 101 的空餘名額)。




好極了,現在我們可以判斷課程是否有空位了。Python 解釋器是檢驗函數的好辦法。將這段代碼保存在文件中,並命名為 scraper.py,然後運行腳本並切入交互模式看看函數的功能:





$

python

-

i

scraper

.

py


>>>

get_open_seats

()


{

"CS 101"

:

1

,

"CS 201"

:

0

}




儘管一切順利,但我們還沒有解決這個問題,我們還需要在空餘名額出現時,想辦法通知用戶。該是 Twilio SMS 出場的時候了!




通過 SMS 獲取更新




構建用戶界面時,我們希望化繁為簡。本程序中,用戶希望在課程座位開放時收到通知。最簡單的解決辦法是分享課程編號,我們通過建立和處理 webhook 實現訂閱功能。我選擇使用 Redis(提供可以從多個進程訪問的數據結構的工具)來存儲訂閱。





# sms_handler.py


from

flask

import

Flask

,

request


import

redis



twilio_account_sid

=

"ACXXXXX"


redis_client

=

redis

.

StrictRedis

(

host

=

"localhost"

,

port

=

6379

,

db

=

0

)


app

=

Flask

(

__name__

)



@

app

.

route

(

"/sms"

,

methods

=

[

"POST"

])


def

handle_sms

()

:


user

=

request

.

form

[

"From"

]


course

=

request

.

form

[

"Body"

].

strip

().

upper

()



redis_client

.

sadd

(

course

,

user

.

encode

(

"utf-8"

))



if

__name__

==

"__main__"

:


app

.

run

(

debug

=

True

)




現在我們使用一個叫做 Flask 的 Python 網路框架來創建小型服務,用於處理 SMS 信息。完成一些初始的設置後,我們設置 handle_sms 函數用於處理 /sms 端點的請求。利用這個函數,我們抓取用戶的手機號以及他們尋找的課程,並將其存儲在以課程命名的集合中。




做到獲取訂閱這步,一切還算順利,但有一個明顯的問題:用戶界面太爛,它不能給用戶提供反饋。我們想要回復用戶,通知我們是否能夠立刻服務他們的要求。要做到這一點,我們將提供一個 TwiML 響應,額外需要的代碼在下方高亮顯示:





# sms_handler.py


from

flask

import

Flask

,

request


import

redis


from

twilio

.

twiml

.

messaging_response

import

MessagingResponse



twilio_account_sid

=

"ACXXXXX"


my_number

=

"+1XXXXXXXXXX"


valid_courses

=

{

"CS 101"

,

"CS 201"

}



redis_client

=

redis

.

StrictRedis

(

host

=

"localhost"

,

port

=

6379

,

db

=

0

)


app

=

Flask

(

__name__

)



def

respond

(

user

,

body

)

:


response

=

MessagingResponse

()


response

.

message

(

body

=

body

)


return

str

(

response

)



@

app

.

route

(

"/sms"

,

methods

=

[

"POST"

])


def

handle_sms

()

:


user

=

request

.

form

[

"From"

]


course

=

request

.

form

[

"Body"

].

strip

().

upper

()


if

course

not

in

valid_courses

:


return

respond

(

user

,

body

=

"Hm, that doesn"t look like a valid course. Try something like "CS 101"."

)



redis_client

.

sadd

(

course

,

user

.

encode

(

"utf-8"

))


return

respond

(

user

,

body

=

f

"Sweet action. We"ll let you know when there are seats available in {course}"

)



if

__name__

==

"__main__"

:


app

.

run

(

debug

=

True

)




我們針對以上代碼做了兩個大的改動。首先,我們驗證用戶是否在尋找一個有效的課程。其次,當用戶請求更新時,我們對其響應。在響應函數中,我們建立了一個 TwiML 響應,用指定的信息內容回復指定的號碼。




確保已安裝 Redis 並通過 redis 伺服器命令啟動它。將上述代碼保存在一個命名為 sms_handler.py 的文件中,並通過 Python 運行它。




誠然,這裡的響應消息有點傻,但我驚訝地看到用戶很喜歡它們。有時候一些人為觸發的反饋能帶來更好的用戶體驗。




現在,讓我們擴展早期的腳本,完善通知功能,真正滿足那些想要在課程開放時獲得通知信息的人。





# scraper.py


from

twilio

.

rest

import

Client



client

=

Client

(

twilio_account_sid

,

token

)


redis_client

=

redis

.

StrictRedis

(

host

=

"localhost"

,

port

=

6379

,

db

=

0

)



def

message

(

recipient

,

body

)

:


message

=

client

.

messages

.

create

(

to

=

recipient

,

from_

=

my_number

,

body

=

body

)




if

__name__

==

"__main__"

:


courses

=

get_open_seats

()


for

course

,

seats

in

courses

.

items

()

:


if

seats

==

0

:


continue



to_notify

=

redis_client

.

smembers

(

course

)


for

user

in

to_notify

:


message

(

user

.

decode

(

"utf-8"

),


body

=

f

"Good news! Spots opened up in {course}. "

+


"We"ll stop bugging you about this one now."

)


redis_client

.

srem

(

course

,

user

)




通過 Python 運行 scraper.py,我們對採集程序進行一次性測試。




使用 Cron 密切關注課程




雖然將查看課程註冊網站的過程簡化成了單個的腳本,我們仍希望腳本能夠隔幾分鐘自動運行一次。通過使用 Cron 能夠輕鬆解決這一問題。運行 crontab-e 並添加以下代碼後,我們可以添加一個每三分鐘運行一次的任務:





*/3 * * * * /path/to/scraper.py




寫入代碼後,Cron 守護進程將每隔三分鐘運行一次我們的採集程序。運行 crontab-l 後,我們可以看到計劃任務。這就完成了!我們訂閱課程更新後,就可以不用管它,專註於我們手邊重要的事情。除了獲得樂趣外,你的朋友會非常感激你,因為你讓他們緊繃的神經得到了舒緩,「輕輕鬆鬆」就能選到想要的課程。依靠這個程序選到了想要的課程無疑是對我努力的最大的回報,但它同時也幫助我周圍的很多人選到了心儀的課程。







(—— CS 101)




(—— 收到,當課程 CS 101 有空位時,我們會立刻通知您!)




(—— 好消息,偵察到課程 CS 101 存在空位,我們將不再發送關於此課程的消息。)




你可以使用本文的技術,為各種不同的事情設置通知。例如,有人用 Ruby 和 Twilio 來跟蹤有沒有工藝啤酒在售。若要獲得本文的所有代碼,請參見這個 gist。你也可以通過以下方式聯繫我:






  • sgt@samueltaylor.org



  • @SamuelDataT




免責聲明:請務必確保設置通知不會違反你所在大學的學生系統服務條款。如有疑問,請詢問知情者!




看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

【Python爬蟲實戰】爬取糗事百科段子
可能是史上最全的機器學習和Python速查表
各種相似性度量及Python實現

TAG:Python |

您可能感興趣

Electrical Engineering Master 選課指南
UC Berkeley學姐經驗分享:美高選課要趁早!
新?考排選課SaaS服務商「?知」獲千萬元Pre-A輪融資 寧澤資本擔任獨家FA
趙懿:公派留美的魔法少女的選課、Job Fair秘籍——乾貨塞不下、精彩看不夠
下學期的選課,我打算用AI來幫助決定了
美國大學的選課形式有哪些?GPA怎麼算?馬上開學了,趕緊進來弄清楚
學習IB課程,選課之前一定要知道這些問題
開智新版 App 與小程序上線,開智文化精選課程賀十一
「選師、選課、走班」,教師培訓新範式,可以實現嗎?| 推薦
開學季,在韓留學生間必上演的災難大片《選課》!
北大通選課、公選課表
體育課選課開啟 你需要這份指南
大學選課,這些雷區一定不要踩!
多倫多大學選課小技巧,幫你擺脫選課難題!
選課走班中的教師:不育人,無法教書
內師大體育必修課、通識課選課通知
《大話西遊》成哈佛教材 , 選課學生增2倍, 教授落淚!
【她 · 教育】留學加拿大的你知道怎麼選課嗎?遵循這幾個原則就好了!
如何在土豆般的選課系統里鬥智斗勇
冬季研學表現優異,選課走班優勢凸顯——我校學子吳萌澤同學在美研學期間通過校園面試