一个小demo

旧文

原文发在**这里 **

假期闲来无事,看书之余突然想起来,总是登录教务网、点击、点击、查询成绩很是麻烦,于是想动手写一个小脚本。遂有此文。

简介

  • 自动登录 ,使用python requests 包来实现;
  • 页面指定内容抓取, 使用BeautifulSoup 包实现;
  • 邮件发送 ,使用SMTP 和 email 包实现

具体内容

涉及到的import

import requests,re
from bs4 import BeautifulSoup
import  types
import  smtplib
from email.mime.text import  MIMEText
import  os

auto login

session = requests.session()
user=input("input your userName:")      		# get user name from  console input
password=input("input your password:")			# get user password from console input	
p=session.post("http://jwas3.nju.edu.cn:8080/jiaowu/login.do", {'userName':user,"password": password})   # This is the login website
request_url = session.get("http://jwas3.nju.edu.cn:8080/jiaowu/student/studentinfo/achievementinfo.do?method=searchTermList")  # the web site we want to get the contents from
request_text=request_url.text 		# get web text
  • 上面的代码很容易理解,建立一个session会话,首先进行post登录,之后get想要抓取内容的网页来获取内容,requests的使用可以查询其文档

两个网址是如何得到的呢?

  • 首先我们打开要抓取的网页,发现它会自动转到一个需要登录的页面
  • 使用chrome NetWork进行跟踪,此时我们人工登录一次,会发现NetWork中会出现类似login命名的一个post方式请求的项,点击查询,会找到对应请求的Header和Form内容
  • 模拟上述进行requests即可

get content from HTML document

抓到对应的表格

soup=BeautifulSoup(request_text)
content_1=soup.body.find_all("tr","TABLE_TR_01")
content_2=soup.body.find_all("tr","TABLE_TR_02")
  • BeautifulSoup 的文档介绍十分简单易懂,可以直接照搬取到想要的内容,文档

一个obj类

class obj:
    def __init__(self,n_z,n_e,t,c,g):
        self.name_zh=n_z
        self.name_en=n_e
        self.type=t
        self.credit=c
        self.grade=g
    def display(self):
        print("name: "+self.name_zh)
        print("name_en: "+self.name_en)
        print("type: "+self.type)
        print("credit: "+self.credit)
        print("grade: "+self.grade)
        print("")
    def getStr(self):
        temp="name: "+self.name_zh+"\nname_en: "+self.name_en+"\ntype: "+self.type+"\ncredit: "+self.credit+"\ngrade: "+self.grade
        temp+="\n"
        return temp
建立了一个obj类方便数据的传递和输出等,obj类的成员就是每个科目的中文名、英文名、科目类型、学分、成绩,display用于调试中展示其内容,getStr返回一个输出字符串,用于我们发送邮件时使用

解析内容建立obj对象列表

obj_list=[]
for i in content_1:
    obj_list.append(parse(i))
for i in content_2:
    obj_list.append(parse(i))
result=""
for i in obj_list:
    #print("order: "+str(j))
    #i.display()
    result+=i.getStr()
    result+="\n"

接着我们从 content_1 和 content_2 的HTML文件中解析出obj对象的成员并加入到list当中

下面是上面用到的parse函数

def parse(content):
    name_zh="";name_en="";types="";study_grade=grade=0;
    pre_list=content.contents                     # 取content的contents成员列表
   # print(pre_list)
    name_zh=pre_list[5].contents[0]               # 这里的下标5、7、9、11、13是从pre_list的内容中人工获得或者find来获得
    name_en=pre_list[7].contents[0]
    type_temp=pre_list[9].contents[0]
    types="".join(type_temp.split())
    study_grade=pre_list[11].contents[0]
    grade=pre_list[13].contents                   # 这里没有直接取contents[0]的原因是有无成绩的情况下,这里的项数会有区分,所以单独在下面进行处理
    if len(grade)==1:
        grade="无成绩"
    else:
        grade=grade[1]
        pattern=re.compile(r'\d+\.\d')
        grade=pattern.findall(str(grade))[0]
    temp=obj(name_zh,name_en,types,study_grade,grade)   # 返回处理好的obj对象
   #temp.display()
    return temp

发送邮件

如何发送?

def sendEmail():
    From="xxxxxx@xx.com"
    To=" xxxxxxxx@xx.com"
    msg=MIMEText(result.encode('utf-8'),_charset='UTF-8')
    msg['Subject']="成绩有改动"
    msg['From']=From
    msg['To'] = To
    s=smtplib.SMTP('smtp.xx.com',25)
    s.login(From,"From password")
    s.sendmail(From,To,msg.as_string())
    s.quit()

发送邮件的方法也见其文档说明,需要注意的是,计算机名需要是英文的,否则对应的库中的编码会出现问题

何时发送?

file=open("copy_local.txt","r+")
result_old=""
for eachline in file:
    result_old+=eachline
print("old: "+result_old)
if result_old!=result:
    sendEmail()
    file.seek(0)
    file.truncate()
    file.write(result)
else:
    print("nothing has changed.")
file.close()
  • 本地建立一个拷贝,每次抓取后和本地副本进行对比,如果相同则不发送,如果不同,则发送邮件并更新本地副本。
  • 这里有很多可以优化的地方,比如并不需要比对全文,可以存储一个项数,这样只需要比较科目数即可,也不需要文件IO的时候将全文均读取

最后

  • 如果没有服务器,这个只是一个demo,没有太大的使用价值,不过如果有服务器或者PC一直开机的话,可以设置上述抓取内容的部分定时进行运行,比如每1h运行一次,这样就可以很好的实现预期的功能了;(阿里云可以申请6个月的服务器,不过没有外网ip,只能从内网ip登陆)
  • 文档和google是我们的好伙伴,上述100行的python代码写的过程中遇到不少细节问题都通过搜索得到了解决;
  • 看书不容易专注的时候给自己定一些小任务来做,也是一种提高啦,而且做完之后更容易看的进去了。
posted @ 2015-05-27 00:05  羽加迪姆勒维奥萨  阅读(357)  评论(0编辑  收藏  举报