基于 Selenium 的作业监视程序

Author Avatar
patrickcty 4月 04, 2017

基于 Selenium 的作业监视程序

闲话

每次计组的作业都是在下课之后在教学平台发布,很多时候都是急着想写作业然后查看结果发现一直没有消息,于是萌生了写一个爬虫自动检测更新,然而要么是因为一直没有写爬虫感觉写不出来于是没有尝试,要么是因为懒而不想去写。

有一次倒是下定决心要去写,不过被处理密码的 JS 卡住了就没有动手写了,这次终于下定了决心,对于最麻烦的登录,就直接用 Selenium 暴力解决了,因为毕竟是个人的小程序,不用考虑性能。总之虽然遇到了一些坑不过还是挺顺利地就搞定了。

Selenium

Selenium 的原理就是直接用代码来操纵浏览器,来完成自动化,我这次选择的是 Chrome,后来测试发现 PhantomJS 这个无头浏览器也可以顺利地运行。

Chrome 版的有些特殊,要安装一个 Chromedriver 的应用,这个所有平台都是有的,目前最新版的 2.28(还被这个版本号小小地坑了一下 233 )。下载链接在这里

接下来就是用 Selenium 的一些操作来模拟浏览器登陆了。

driver = webdriver.Chrome('/path/to/chromedriver')
driver.get('http://study.jnu.edu.cn')

# 总之找到登录框就好,然后就这样填充表单
elem = driver.find_element_by_class('XXX')
# 填充表单
elem.send_keys('username')

# 假设密码已经填好了
# 找到登陆的按钮
elem = driver.find_element_by_class('XXX')
# 模拟按的操作,这样就可以了
elem.click()

相关教程可以看这里

XPath

XPath介绍

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

有些直接根据 Class 等很难定位,于是用 Xpath 可以很轻松愉快地解决。

语法的话可以参考这个

代码

贴一个完整的代码:

#! /usr/bin/env python3

from selenium import webdriver
import time
import os
from mailalert import sendMail


class HomeworkIndicator:

    def __init__(self, urls, names):

        self.driver = webdriver.Chrome('/home/patrick/Softwares/chromedriver')
        self.urls = urls
        self.hw_len = [0 for i in self.urls]
        self.names = names

    def login(self):

        self.driver.get('http://study.jnu.edu.cn')

        name = self.driver.find_element_by_name('user_id')
        paswd = self.driver.find_element_by_name('password')

        name.send_keys(os.environ.get('STUDY_NAME'))
        paswd.send_keys(os.environ.get('STUDY_PASS'))

        path = '//tbody/tr[3]/td[2]/input'
        self.driver.find_element_by_xpath(path).click()

    def start(self):

        self.login()

        path = '//ul/li[@class=\'clearfix read\']'
        i = 0
        for url, hw, name in zip(self.urls, self.hw_len, self.names):
            self.driver.get(url)
            self.hw_len[i] = len(self.driver.find_elements_by_xpath(path))
            i += 1

        while 1:
            i = 0
            for url, hw, name in zip(self.urls, self.hw_len, self.names):
                self.driver.get(url)
                cnt = len(self.driver.find_elements_by_xpath(path))
                if cnt > hw:
                    self.hw_len[i] = cnt
                    body = '【{}】作业有新内容了!'.format(name)
                    print('已发送邮件!')
                    sendMail('作业更新提醒!', body)
                i += 1
                time.sleep(3)
            time.sleep(3600)


if __name__ == '__main__':

    urls = ['http://study.jnu.edu.cn/webapps/blackboard/content/listConte'
            'nt.jsp?course_id=_18789_1&content_id=_340261_1',
            'http://study.jnu.edu.cn/webapps/blackboard/content/listConte'
            'nt.jsp?course_id=_18755_1&content_id=_192521_1',
            'http://study.jnu.edu.cn/webapps/blackboard/content/listConte'
            'nt.jsp?course_id=_18755_1&content_id=_251306_1']
    names = ['计组', '汇编', '汇编实验']
    indicator = HomeworkIndicator(urls, names)
    indicator.start()

感想

其实使用 Selenium 来完成是十分简单的,不过之前一直有一些偷懒以及害怕自己不行的想法在阻碍着自己动手操作,这段时间独自写代码真的太少了,以后还是要像这样直面问题才行啊。