以前专门搞java的,现在发现python相比于更加方便,python底层做了更多的工作。

用python爬取教务系统获取成绩课表等信息。过程中遇到的问题,怎么解决。现在做一个总结。

#encoding:utf-8
import tornado.ioloop
import tornado.web
from tornado.escape import json_decode

import edu #自己后台处理的python文件

#用来接收前端请求  并响应  json格式
class login(tornado.web.RequestHandler):
    def get(self):
        """get请求"""
        #前后端使用json
        uid = self.get_body_argument('user')
        pwd = self.get_body_argument('password')
        openid = self.get_body_argument('openId')
        week = self.get_body_argument('week')
        result = edu.login(uid, pwd, openid, week)
        respon_json = tornado.escape.json_encode(result)
        self.write(respon_json)
    def post(self):
        print(self.request.body)
        data = json_decode(self.request.body)
        uid = data['user']
        pwd = data['password']
        openid = data['openId']
        week = data['week']
        result = edu.login(uid, pwd, openid, week)
        respon_json = tornado.escape.json_encode(result)
        self.write(respon_json)


#启动服务端   localhost:8888/edu/login  
application = tornado.web.Application([(r"/edu/login", login)])
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
#操作数据库相关的
获取一个连接
def getCur():
    connect = pymysql.connect(
        host='',
        port=,
        user='',
        passwd=',
        db='',
        charset='utf8'
    )
    return connect

# # 使用 cursor() 方法创建一个游标对象 cursor
# cursor = connect.cursor()
#
# # 使用 execute()  方法执行 SQL 查询
# cursor.execute("SELECT VERSION()")
#
# # 使用 fetchone() 方法获取单条数据.
# data = cursor.fetchone()

 

#后端逻辑处理模块

#需要导入的模块

#https
import ssl
#可以处理表格的那种欣喜
import pandas as pd
from http import cookiejar
from urllib import request,parse
import urllib
import pymysql
#用于解析
from bs4 import BeautifulSoup
#请求
import requests
#可以用于处理pdf文件
import fitz
#多线程模块
import _thread

#这些url 打开chorme 调试着模式获取到相应的地址
eduURL = ""
loginURL = ""
scopeURL = ""
timetableURL = ""

#模拟登录测试模块   保存一个会话
#声明一个CookieJar对象实例来保存cookie
cookie = cookiejar.CookieJar()
#利用urllib.request库的HTTPCookieProcessor对象来创建cookie处理器,也就CookieHandler
handler=request.HTTPCookieProcessor(cookie)
#通过CookieHandler创建opener
opener = request.build_opener(handler)
#此处的open方法打开网页
# 不验证https 请求https时会验证ssl证书等
ssl._create_default_https_context = ssl._create_unverified_context
# 登录方法
def login(username, password, openid, week):
    print("登录中")
    # 构造请求参数  post的方式
    loging_data = parse.urlencode([
        ("j_username", username),
        ("j_password", password)
    ])
    # 构造请求头
    headers = {
        "User-Agent": " Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Mobile Safari/537.36",
    }
    #发起请求
    req = request.Request(url=loginURL,
                          data=loging_data.encode(encoding='utf-8'),
                          headers=headers)
    try:
        result = opener.open(req)  # 访问请求的链接
        soup = BeautifulSoup(result.read().decode('utf-8'), "html.parser")
        #具体的成功页面自己判断  我这边失败的话 回调到登录页面 我验证下是否有form标签来判断是否成功
        ans = soup.find_all("form")
        if ans:
            print("登录失败....")
            return False
        else:
            print("登录成功....")
            # 连接数据库
            connect = getCur()
            cur = connect.cursor()
            selectSql = "select * from user where openid = '%s'"%(openid)
            print(selectSql)
            cur.execute(selectSql)
            data = cur.fetchall()
            if data:
                print(data)
            else:
                sql = "insert  into user(uid,pwd,openid) values('%s' ,'%s','%s')" % (username, password, openid)
                print(sql)
                cur.execute(sql)
                print("插入数据成功")
                #获取成绩 课表   异步化处理 减小响应时间
                _thread.start_new_thread(getTimeTable, (week, username),)
                _thread.start_new_thread(getCourse, (openid,))
            connect.commit()
            connect.close()
        return True
    except urllib.error.HTTPError:
        print("connect failed")

获取成绩(表格或者pdf形式)  获取课表(网页中是表格) 将网页中的数据获取并存储到数据库中

#获取课表
def getTimeTable(week, username):
    try:
        print("开始爬取课表")
        timetableURL = ""
        headers = {

            "User-Agent": " Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Mobile Safari/537.36",
        }
        req = request.Request(url=timetableURL,
                              headers=headers)
        result = opener.open(req)  # 进入教务系统
        #获取一个数据库的连接 实现在上面的代码中
        con = getCur()
        cur = con.cursor()
        #读取获取的页面中的数据  并用pandas模块将表格提取出来
        df = pd.read_html(result.read().decode('utf-8'))[0]
        list = ["Mon", "Tue", "Wed", "Thu", "Fri","Sat"]
        // 遍历  这块如果有什么不懂可以私聊我  一次探讨下
        for index, row in df.iterrows():
            for item in list:
                if not (pd.isna(row[item])):
                   insertSql = "insert into timetable(course,weekday,period,week,username) values('%s','%s','%s','%s','%s')" % (row[item],
                                                    list.index(item)+1, index+1, week, username)
                   print(insertSql)
                   cur.execute(insertSql)
        con.commit()
        con.close()
        print("爬取课表成功 并且存入数据库")
    except urllib.error.HTTPError:
        print("error")
#获取成绩
def getCourse(openid):
    try:
        print("开始爬取成绩")
        courseURL = ""
        courseTime1=""
        req = request.Request(url=courseURL,
                              headers=headers,
                              data=loging_data.encode(encoding='utf-8'))

        # 因为我这个教务系统的成绩是pdf文件形式的  获取pdf文件流  将数据流写入到文件中注意是 wb  b代表二进制的形式
        result1 = opener.open(req1)  # 进入教务系统
        f = open("/root/workspace/pdf/course.pdf", 'wb')
        block_sz = 8192
        while True:
            buffer = result1.read(block_sz)
            if not buffer:
                break
            f.write(buffer)
        doc = fitz.open('/root/workspace/pdf/course.pdf')
        # 这一步就是将pdf文件解析成多张图片   你要从pdf文件中解析出对应的成绩不太容易,因为pdf中无法按照什么规则去解析  显示在前端可以用多张图片  图片就更容易  我是用nginx做图片服务器
        for pg in range(doc.pageCount):
            page = doc[pg]
            rotate = int(0)
            # 每个尺寸的缩放系数为2,这将为我们生成分辨率提高四倍的图像。
            zoom_x = 3.0
            zoom_y = 2.0
            trans = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
            pm = page.getPixmap(matrix=trans, alpha=False)
            pm.writePNG('/root/workspace/static/%s%s.png' % (openid, pg + 1))
    except urllib.error.HTTPError:
        print("error")

服务器上搭建python3环境遇到的问题

分享自己写的python的启动脚本  

#!/bin/sh

NAME=python
echo $NAME
ID=`ps -ef | grep "$NAME" | grep -v "$0" | grep -v "grep" | awk '{print $2}'`
echo $ID
echo "---------------"
for id in $ID
do
kill -9 $id
echo "killed $id"
done
echo "---------------"

#! kill之前的python程序   重新启动后台程序  启动对应的程序  输出日志到这个文件中
nohup python3 -u server.py > /root/workspace/edu/out.log 2>&1 &
echo "启动成功"