利用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 相关文章推荐
Python2.x版本中maketrans()方法的使用介绍
May 19 Python
Python可变参数函数用法实例
Jul 07 Python
Python实现查找匹配项作处理后再替换回去的方法
Jun 10 Python
使用Numpy读取CSV文件,并进行行列删除的操作方法
Jul 04 Python
解决python3 Pycharm上连接数据库时报错的问题
Dec 03 Python
Python图像处理之gif动态图的解析与合成操作详解
Dec 30 Python
查看Python依赖包及其版本号信息的方法
Aug 13 Python
python实现图片上添加图片
Nov 26 Python
python多线程使用方法实例详解
Dec 30 Python
Python map及filter函数使用方法解析
Aug 06 Python
解决Windows下python和pip命令无法使用的问题
Aug 31 Python
python反爬虫方法的优缺点分析
Nov 25 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
PHPMailer安装方法及简单实例
2008/11/25 PHP
php json相关函数用法示例
2017/03/28 PHP
PHP实现搜索时记住状态的方法示例
2018/05/11 PHP
js资料prototype 属性
2007/03/13 Javascript
use jscript with List Proxy Server Information
2007/06/11 Javascript
js 禁用只读文本框获得焦点时的退格键
2010/04/25 Javascript
基于jquery的一个浮动框(扩展性比较好 )
2010/08/27 Javascript
jquery解析XML字符串和XML文件的方法说明
2014/02/21 Javascript
JS实现生成会变大变小的圆环实例
2015/08/05 Javascript
纯javascript实现图片延时加载方法
2015/08/21 Javascript
javascript如何定义对象数组
2016/06/07 Javascript
JavaScript中值类型和引用类型的区别
2017/02/23 Javascript
Angular2使用Angular-CLI快速搭建工程(二)
2017/05/21 Javascript
vue页面切换到滚动页面显示顶部的实例
2018/03/13 Javascript
React 使用recharts实现散点地图的示例代码
2018/12/07 Javascript
微信小程序+云开发实现欢迎登录注册
2019/05/24 Javascript
three.js 利用uv和ThreeBSP制作一个快递柜功能
2020/08/18 Javascript
PyQt5图形界面播放音乐的实例
2019/06/17 Python
python 并发编程 多路复用IO模型详解
2019/08/20 Python
使用python 对验证码图片进行降噪处理
2019/12/18 Python
TensorFlow基本的常量、变量和运算操作详解
2020/02/03 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
css3类选择器之结合元素选择器和多类选择器用法
2017/03/09 HTML / CSS
ivx平台开发之不用代码实现一个九宫格抽奖功能
2021/01/27 HTML / CSS
园林资料员岗位职责
2013/12/30 职场文书
八一建军节感言
2014/02/28 职场文书
高级工程师英文求职信
2014/03/19 职场文书
学校综治宣传月活动总结
2014/07/02 职场文书
世界卫生日宣传活动总结
2015/02/09 职场文书
2015年教育实习工作总结
2015/04/24 职场文书
文化大革命观后感
2015/06/17 职场文书
2016年教师师德师风心得体会
2016/01/12 职场文书
教师节作文之小学四年级
2019/09/03 职场文书
Java SSM配置文件案例详解
2021/08/30 Java/Android
MySQL详解进行JDBC编程与增删改查方法
2022/06/16 MySQL
python数字图像处理实现图像的形变与缩放
2022/06/28 Python