使用Scrapy登入帳號與抓取資料

目前已經無法使用,zerojudge更新登入系統的機制,但可用於其他帳號密碼登入的網站。

可以經由撰寫幾行程式,透過Scrapy模組登入帳號與抓取資料,當然要事先了解Scrapy的運作流程。經由本程式以登入zerojudge與擷取指定的使用者AC的題數為範例,幫助教師可以隨時掌握學生的AC題數,學期末登分使用。

安裝Scrapy與建立專案

Step1)安裝Scrapy

執行「pip install scrapy」,因為使用Anaconda3,本身已經內建scrapy,所以就沒有安裝scrapy。

Step2)建立專案

在命令提示字元下,執行指令「scrapy startproject zj」,建立專案zj

Step3)建立spider

在命令提示字元下,執行指令「scrapy genspider zero zerojudge.tw」,建立名稱zero的spider,指定擷取網站 zerojudge.tw

一個專案可以有許多spider,每個spider使用「scrapy crawl 指定的spider」,就可以使用指定的spider抓取資料。

此時在Windows命令提示字元下,使用指令「tree /F」可以列出目前資料夾下與檔案的狀態,除了zj\spider\zero.py為指令「scrapy genspider zero zerojudge.tw」所建立,其餘都是指令「scrapy startproject zj」所建立,以下說明各個檔案的用途。

D:\jupyter\zj> tree /F

列出磁碟區 Data 的資料夾 PATH

磁碟區序號為 8E74-5782

D:.

│ scrapy.cfg

└─zj

│ items.py ===========>儲存資料的結構

│ middlewares.py ======>分成spider middleware與downloader middleware

│ pipelines.py =========>用於整理、過濾與刪除資料item,並將資料插入資料庫

│ settings.py ==========>設定檔案

│ __init__.py

└─spiders ===========>所有spider放在此資料夾

zero.py =============>剛剛使用指令「scrapy genspider zero zerojudge.tw」建立的spider

__init__.py

建立抓取資料的結構與spider程式碼

Step4)編輯item.py,建立抓取資料的結構,目前建立acc接收zerojudge的帳號,ac為該帳號AC的題數。

Step5)編輯zj/spiders/zero.py,製作登入帳號與擷取網頁的程式

查看https://zerojudge.tw/Login的原始網頁的第561到576行發現登入的網頁,帳號的標籤input的屬性name為account,密碼的標籤input的屬性name為passwd,等一下設定帳號與密碼時會使用到。

查詢其他使用者AC題數,需要登入zerojudge帳號才能查詢,以下程式使用scrapy.FormRequest進行帳號與密碼登入。scrapy預設抓取start_urls所指定的網址,抓取後自動呼叫函式parse(第5到10行)進行資料處理,在函式parse內宣告結構data(第6行到第9行),,使用account設定zerojudge帳號,使用passwd設定zerojudge密碼,接著使用scrapy.FormRequest進行帳號與密碼登入,設定url為登入的網址,formdata為結構data,使用callback設定登入後執行函式parse_user。

函式parse_user從串列userlist取得使用者帳號,並透過「https://zerojudge.tw/UserStatistic?account=」查詢串列userlist的每一個使用者帳號的AC題數,最後呼叫函式parse_user_process找出使用者的AC題數(第14到15行),函式parse_user_process等一下介紹。

函式parse_user_process透過網址「https://zerojudge.tw/UserStatistic?account=使用者帳號」擷取使用者帳號的AC題數,將帳號放置於變數account,AC題數放置於變數ac,將帳號與AC題數放到item內,最後回傳item,scrapy會自動處理成使用者指定的格式。

使用「response.xpath('//button/@data-receiver')」可以存取到帳號,因為執行「https://zerojudge.tw/UserStatistic?account=使用者帳號」回傳的網頁如下。

根據上方網頁,利用「response.xpath('//button/@data-receiver')」可以存取到標籤button的屬性data-receiver的值就是帳號。

根據上方網頁,利用「//p[@align="left"]/a/text()」可以存取到屬性align為left的標籤p,取出下方標籤a所包夾的文字,得到AC題數,而函式extract_first表示取出第一個元素。

Step6)執行scrapy專案,在第一層的zj資料夾下,該zj資料夾內有檔案「scrapy.cfg」,在命令提示字元下執行指令「scrapy crawl zero -o ac.json」,表示執行檔名為zero的spider,將item轉換成json格式輸出,在第一層的zj資料夾下,產生檔案ac.json,該檔案內儲存指定使用者帳號的AC題數。

zero.py的完整程式碼如下。

本程式使用限制:因為沒有執行Logout,zerojudge有帳號的連線個數限制,若出現錯誤500表示超過連線次數,可以更換帳號,或者等待一段時間後再連線。