利用Python实现图书超期提醒


Posted in Python onAugust 02, 2016

一、模拟登录图书馆管理系统

我们可以先看一下登录页面(很多学校这些管理系统页面就是很low):

利用Python实现图书超期提醒

两种方式去模拟登录图书馆:

1. 构造登录表单进行模拟登录

这种方式模拟登录似乎是很可靠的,但有时候就是在验证码获取上很困难,如果简单的网站,有的会利用当前时间戳来构造验证码,这种就很容易从网页上观察出来,但比如我们这次要模拟登录的网站似乎是不能这样做,因为它是使用JavaScript标准库里的Math函数直接随机生成的验证码链接,可以从下面图片上观察验证码处的代码:

利用Python实现图书超期提醒

它使用Math.random()函数返回 [0-1) 的浮点值伪随机数(大于等于0,小于1)
好吧!我们换用一种比这个更简单的方式模拟登录吧!

2. 通过Cookie登录图书馆

Cookie,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。

这里我们使用Requests库来进行模拟登录过程,在这之前我们还有个问题,怎么获取Cookie呢??
如果你使用的是谷歌浏览器,那你可以通过按F12就可以看到下图里面有个Cookie的内容,这就是你要的东西:

利用Python实现图书超期提醒

再上个图分析一下,希望大家能有耐心读下去:

利用Python实现图书超期提醒

通过图片我们知道可以获取借阅日期和应还日期,获取日期后根据应还日期和当前日期比较,就可以得出是否超期的结果。不多说,先贴代码再说:

import requests
session = requests.Session()  # 会话对象让你能够跨请求保持某些参数,它也会在同一个Session实例发出的所有请求之间保持cookie
session.headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36',
  'Cookie': 'ASP.NET_SessionId=1qri0rmoylpyrs45rurzme55; Hm_lvt_ed06d5e5f94d85932b82e4aac94d0c68=1467535679,1469713840; Hm_lpvt_ed06d5e5f94d85932b82e4aac94d0c68=1469713840; PHPSESSID=ev339udv0rrhqg6tfdvfukqos1'
}

上述代码使用了requests的会话对象来保存Cookie, 如果我们需要跳转到其它页面,我们不用每次都模拟登录,因为cookie已经保存了我们的登录状态。

会不会有人疑问,不是要说模拟登录的吗??怎么没有这过程呢??

其实我们上面代码中的Cookie已经保存了我们的登录状态,相当于我们已经模拟登录过了,这样子模拟登录是不是简单多了,但缺点是我们需要手动在登录页面输入一遍,然后再从登录页面找到cookie粘贴到代码中来

二、获取所借书籍信息

利用Python实现图书超期提醒

通过分析页面,我们可以使用BeautifulSoup来提取我们需要的内容,我们需要的是书籍的条形码、题名和作者、借阅日期、应还日期,其实我们只需要应还日期就行,但为了以后需要,先获取书籍的所有信息并保存进数据库里面:

 利用Python实现图书超期提醒

定义了一个数据库操作的函数,方便以后调用

def get_mysql():
  conn = pymysql.connect(host = 'localhost', user = 'root', passwd = '2014081029', db = 'mysql', charset = 'utf8')  # user为数据库的名字,passwd为数据库的密码,一般把要把字符集定义为utf8,不然存入数据库容易遇到编码问题
  cur = conn.cursor()  # 获取操作游标
  cur.execute('use book')  # 使用book这个数据库
  return (cur, conn)

定义一个函数来获取图书信息并保存:

def get_book_name(book_url):
  html = session.get(book_url, cookies = cookie, headers = headers).content.decode('utf-8')
  soup = BeautifulSoup(html, 'lxml')
  book_bar = []  # 书籍的条形码列表,用来判断要存入数据库的书籍是否已经存在

  cur, conn = get_mysql()
  sql = 'select * from book_list;'
  cur.execute(sql)
  rows = cur.fetchall()
  for row in rows:
    book_bar.append(row[1])

  book_list = []  # 这个是我测试时使用的,作用是把每本书籍的信息列表放在这个列表中
  book_every = [] # 一本书籍的所有信息列表
  for book_time in soup.find_all('td', class_="whitetext"):
    print(book_time.get_text().strip()) # 移除字符串头尾指定的字符(默认为空格)
    pattern = re.compile(r'\s')
    content = re.sub(pattern, r'', book_time.get_text()) # 目的也是匹配任何空白符并去除,貌似对空行去除没影响

    if content != '':
      book_every.append(content)
      if len(book_every) == 7:
        book_list.append(book_every)
        if book_every[0] not in book_bar:
          sql = 'insert book_list(条形码, 题名和作者, 借阅日期, 应还日期, 续借量, 馆藏地, 附件) value(' + "\'" \
             + book_every[0] + "\'," + "\'" + book_every[1] + "\'," + "\'" + book_every[2] + "\'," + "\'" \
             + book_every[3] + "\'," + "\'" + book_every[4] + "\'," + "\'" + book_every[5] + "\'," + "\'" \
             + book_every[6] + "\'" + ');'
        try:

          cur.execute(sql)
          conn.commit()
        except:
          conn.rollback()
        book_every = []

  print(book_list)

接下来我们分析一下上面代码中没有注释的代码,首先我们先把处理后的信息加入book_every列表中,然后从页面源代码(tp9.png)中我们可以知道,一本书信息中只需要前面7项内容,因此我们使用一个判断语句:

if len(book_every) == 7:
  book_list.append(book_every)
  if book_every[0] not in book_title:
    sql = 'insert book_list(条形码, 题名和作者, 借阅日期, 应还日期, 续借量, 馆藏地, 附件) value(' + "\'" \
             + book_every[0] + "\'," + "\'" + book_every[1] + "\'," + "\'" + book_every[2] + "\'," + "\'" \
             + book_every[3] + "\'," + "\'" + book_every[4] + "\'," + "\'" + book_every[5] + "\'," + "\'" \
             + book_every[6] + "\'" + ');'
    try:
      cur.execute(sql)
      conn.commit()    
    except:
      conn.rollback()  # 如果存入数据库失败,执行回滚操作
  book_every = []

也就是说,如果判断出book_every已经达到7项内容,就执行存入数据库的操作,然后在把book_every重置为空列表

三、发送邮件提醒功能

先贴上代码:

def send_message():
  day_num = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  day_num1 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  sql = 'select * from book_list;'
  cur, conn = get_mysql()
  cur.execute(sql)
  rows = cur.fetchall()
  local_time = time.strftime("%Y-%m-%d", time.localtime()) # 获取当前时间
  local_time = str(local_time)
  times = re.split(r'-', local_time)
  year = times[0]

  number = 0
  while(True):
    for i in rows:
      print(i[4])
      pattern = re.split(r'-', i[4])
      if times[1] == pattern[1]:
        day = int(times[2]) - int(pattern[2])
        if day > 0:
          print('已经超期了%d天' % day)
          number += 1
          send_email(day, number, i[2])
      elif times[1] > pattern[1]:
        if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
          extend_day = day_num1[int(pattern[1]) - 1] - int(pattern[2]) + times[2]
          print('已经超期了%d天' % extend_day)
          number += 1
          send_email(day, number, i[2])
        else:
          extend_day = day_num[int(pattern[1]) - 1] - int(pattern[2]) + times[2]
          print('已经超期了%d天' % extend_day)
          number += 1
          send_email(day, number, i[2])

      else:
        print('还没有超期的书籍')

      print(pattern[2])
    time.sleep(3600 * 24)

我们来分析代码吧,首先我们判断是否超期是根据当前时间和应还日期的相加减得到的,所以我们考虑到:

    1.如果应还日期是上个月,这里我们就要进行月份的相加减,因为闰年和平年的月份不一样,所以我们定义了day_num和day_num1两个列表来表示闰年和平年的月份天数。

    2.然后我们使用月份当做判断条件来比较超期天数

月份判断,如果当前月份等于应还月份,就执行下面操作,注意里面已经包含发送邮件函数,下面会贴出发送邮件函数,大家也许会想,为什么没有判断年份,因为我一般借书不会超期这么久,所以没有加上这个判断

if times[1] == pattern[1]:
        day = int(times[2]) - int(pattern[2])
        if day > 0:
          print('已经超期了%d天' % day)
          number += 1
          send_email(day, number, i[2])

然后是当前月份大于应还月份时,这时候就有闰年和平年的判断了

elif times[1] > pattern[1]:
        if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
          extend_day = day_num1[int(pattern[1]) - 1] - int(pattern[2]) + times[2]
          print('已经超期了%d天' % extend_day)
          number += 1
          send_email(day, number, i[2])

下面贴出发送邮件的代码:

def send_email(day, number, title):
  from_addr = '15602200534@163.com'
  password = '就不告诉你'
  to_addr = '673411814@qq.com'
  smtp_server = 'smtp.163.com'

  text = 'Hello ,郭伟匡, 告诉你一个不好的消息,赶紧带上你的书,去图书馆交钱吧!你有一本叫《%s》的书籍超期了' \
      ',而且已经超期了%d天了,总共有%d书超期了!!!' % (title, day, number)
  msg = MIMEText(text, 'plain', 'utf-8')
  msg['From'] = format_addr('图书馆的通知<%s>' % from_addr)
  msg['To'] = format_addr('管理员<%s>' % to_addr)
  msg['Subject'] = Header('来着郭伟匡的问候......', 'utf-8').encode()

  server = smtplib.SMTP(smtp_server, 25)
  server.set_debuglevel(1)
  server.login(from_addr, password)
  server.sendmail(from_addr, [to_addr], msg.as_string())
  server.quit()

最后把把发送邮件的截图发出来:

 利用Python实现图书超期提醒

以上就是利用Python实现图书超期提醒的全部内容,这个功能还是挺实用的,感兴趣的小伙伴可以自己动手实践起来。希望对大家学习Python有所帮助。

Python 相关文章推荐
python使用7z解压apk包的方法
Apr 18 Python
TensorFlow saver指定变量的存取
Mar 10 Python
使用python画个小猪佩奇的示例代码
Jun 06 Python
基于python实现KNN分类算法
Apr 23 Python
Pandas统计重复的列里面的值方法
Jan 30 Python
Python3的高阶函数map,reduce,filter的示例详解
Jul 23 Python
python tornado修改log输出方式
Nov 18 Python
python实现简单日志记录库glog的使用
Dec 13 Python
Python实现GIF图倒放
Jul 16 Python
Python selenium如何打包静态网页并下载
Aug 12 Python
Django展示可视化图表的多种方式
Apr 08 Python
python编程实现清理微信重复缓存文件
Nov 01 Python
Python正规则表达式学习指南
Aug 02 #Python
Python实现SMTP发送邮件详细教程
Mar 02 #Python
python logging 日志轮转文件不删除问题的解决方法
Aug 02 #Python
python中的字典使用分享
Jul 31 #Python
Python随机生成数据后插入到PostgreSQL
Jul 28 #Python
python3新特性函数注释Function Annotations用法分析
Jul 28 #Python
python中的格式化输出用法总结
Jul 28 #Python
You might like
destoon设置自定义搜索的方法
2014/06/21 PHP
PHP编写学校网站上新生注册登陆程序的实例分享
2016/03/21 PHP
php生出随机字符串
2017/07/06 PHP
js或css实现滚动广告的几种方案
2010/01/28 Javascript
JavaScript常用对象的方法和属性小结
2012/01/24 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
jQuery Form 页面表单提交的小例子
2013/11/15 Javascript
jquery.post用法示例代码
2014/01/03 Javascript
node.js中的favicon.ico请求问题处理
2014/12/15 Javascript
jQuery插件pagination实现分页特效
2015/04/12 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
精彩的Bootstrap案例分享 重点在注释!(选项卡、栅格布局)
2016/07/01 Javascript
JavaScrpt判断一个数是否是质数的实例代码
2017/06/11 Javascript
第一个Vue插件从封装到发布
2017/11/22 Javascript
Vue中this.$router.push参数获取方法
2018/02/27 Javascript
在Vue中使用axios请求拦截的实现方法
2018/10/25 Javascript
浅谈Vue的响应式原理
2019/05/30 Javascript
vue.js实现数据库的JSON数据输出渲染到html页面功能示例
2019/08/03 Javascript
ligerUI的ligerDialog关闭刷新的方法
2019/09/27 Javascript
[01:00:14]2018DOTA2亚洲邀请赛 4.6 淘汰赛 VP vs TNC 第三场
2018/04/10 DOTA
python 解析html之BeautifulSoup
2009/07/07 Python
Python过滤函数filter()使用自定义函数过滤序列实例
2014/08/26 Python
python数据清洗系列之字符串处理详解
2017/02/12 Python
python DataFrame转dict字典过程详解
2019/12/26 Python
VS2019+python3.7+opencv4.1+tensorflow1.13配置详解
2020/04/16 Python
Python数组拼接np.concatenate实现过程
2020/04/18 Python
西班牙英格列斯百货法国官网:El Corte Inglés法国
2017/07/09 全球购物
女孩每月服装订阅盒:kidpik
2019/04/17 全球购物
delegate与普通函数的区别
2014/01/22 面试题
事业单位绩效考核实施方案
2014/03/27 职场文书
弘扬焦裕禄精神走群众路线思想汇报
2014/09/12 职场文书
官僚主义现象查摆问题整改措施
2014/10/04 职场文书
故意伤害罪辩护词
2015/05/21 职场文书
主持人大赛开场白
2015/05/29 职场文书
Canvas跟随鼠标炫彩小球的实现
2021/04/11 Javascript
Django使用redis配置缓存的方法
2021/06/01 Redis