需求 媳妇最近需要参加普通话考试,由于她是社会考生,很难报上名。(武汉市上一次举行社会考生参加普通话考试还是去年的12月份)基于此,媳妇想让我帮她写一个程序,监控普通话考试的报名信息。那我的python就大有用处了!
过程 既然要监控普通话考试的报名信息,肯定有一个目标网站。找来找去找到华中师范大学的普通话测试通知网页https://www.ccnu.edu.cn/shfw/pthcs.htm
以及湖北普通话水平测试在线报名系统http://hubeibm.cltt.org/pscweb/signUp.html
。华师的网页是一个静态页面,比较好处理,使用python的lxml库将文本解析为html,使用xpath即可解析需要的数据。 初步对湖北普通话报名系统使用xpath解析时得到数据很明显无法使用(怀疑使用了反爬技术),退而求其次,咱可以使用python+selenium对网页进行截图,然后将图片进行压缩转成base64,发送到微信企业号,就可以进行监控报名系统了,大功告成!
开发 环境 通过前面的分析,本次需求的实现需要用到的第三方库,依次使用pip install 安装如下依赖
1 2 3 4 5 requests==2.25.1 lxml==4.6.3 APScheduler==3.7.0 selenium==3.141.0 pillow==8.2.0
code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 import base64import ioimport osimport timeimport requestsfrom PIL import Imagefrom lxml import etreefrom apscheduler.schedulers.blocking import BlockingSchedulerfrom selenium import webdriverfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesdef send_message (title, content ): url = 'https://sctapi.ftqq.com/SCT3143xxxxxxxxxcHKuDrRablnsELSCi.send' param = { 'title' : title, 'desp' : content } requests.post(url, data=param) def job (): url = "https://www.ccnu.edu.cn/shfw/pthcs.htm" try : text = requests.get(url).content html = etree.HTML(text) title = html.xpath('//*[@id="container"]/div[3]/div/div[2]/div/div/div/h3/strong/span' )[0 ].text.strip() date = html.xpath('//*[@id="vsb_content_6"]/p[53]' )[0 ].text.strip() content = '{} \r\n' \ '{} \r\n' \ '{}' .format (title, date, url) send_message("普通话考试信息通知" , content) except Exception as e: print("has some error" ) send_message("普通话考试信息通知" , "爬虫获取信息失败,请手动点击 {}" .format (url)) def compress_image_bs4 (b64, mb=190 , k=0.9 ): """不改变图片尺寸压缩到指定大小 :param outfile: 压缩文件保存地址 :param mb: 压缩目标,KB :param step: 每次调整的压缩比率 :param quality: 初始压缩比率 :return: 压缩文件地址,压缩文件大小 """ f = base64.b64decode(b64) with io.BytesIO(f) as im: o_size = len (im.getvalue()) // 1024 if o_size <= mb: return b64 im_out = im while o_size > mb: img = Image.open (im_out) x, y = img.size out = img.resize((int (x * k), int (y * k)), Image.ANTIALIAS) im_out.close() im_out = io.BytesIO() out.save(im_out, 'png' ) o_size = len (im_out.getvalue()) // 1024 b64 = base64.b64encode(im_out.getvalue()) im_out.close() return str (b64, encoding='utf8' ) def job2 (): url = "http://hubeibm.cltt.org/pscweb/signUp.html" driver = webdriver.Remote( command_executor="http://10.122.100.146:4444/wd/hub" , desired_capabilities=DesiredCapabilities.CHROME ) driver.get(url) wh = driver.find_element_by_xpath('/html/body/div[2]/div[2]/div/div[1]/online-widget/div/div[1]/ul/li[2]/a' ) wh.click() time.sleep(1 ) pic_name = r'{}_screen.png' .format ('test' ) driver.save_screenshot(pic_name) with open (pic_name, "rb" ) as f: base64_data = base64.b64encode(f.read()) base64_data = compress_image_bs4(base64_data, 30 , 0.9 ) content = "普通话测试截图" \ "![image](data:image/png;base64,{})" .format (base64_data) send_message("普通话测试截图" , content) driver.close() os.remove(pic_name) if __name__ == '__main__' : job2() job() scheduler = BlockingScheduler() scheduler.add_job(job, 'interval' , seconds=10800 ) scheduler.add_job(job2, 'interval' , seconds=10800 ) scheduler.start()
工程化 docker化 1 2 3 4 5 6 7 FROM python:3.7 WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . ENTRYPOINT ["python"] CMD ["./main.py"]
1 2 3 4 5 6 7 8 sudo docker run -d -p4444:4444 selenium/standalone-chrome:latest mkdir pthcs cd pthcssudo docker build -t pthcs:v0.1 . sudo docker run -d pthcs:v0.1
结束语 只为记录日常代码,内容比较琐碎,轻喷。。。