利用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之wxPython菜单使用详解
Sep 28 Python
浅析Python中的多进程与多线程的使用
Apr 07 Python
Python中扩展包的安装方法详解
Jun 14 Python
Python 利用scrapy爬虫通过短短50行代码下载整站短视频
Oct 29 Python
python 获取毫秒数,计算调用时长的方法
Feb 20 Python
利用pandas合并多个excel的方法示例
Oct 10 Python
Python将列表中的元素转化为数字并排序的示例
Dec 25 Python
python使用正则表达式去除中文文本多余空格,保留英文之间空格方法详解
Feb 11 Python
python argparse传入布尔参数false不生效的解决
Apr 20 Python
pymysql模块使用简介与示例
Nov 17 Python
python中的时区问题
Jan 14 Python
Python命令行参数argv和argparse该如何使用
Feb 08 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
PHP实现类似题库抽题效果
2018/08/16 PHP
JavaScript和ActionScript的交互实现代码
2010/08/01 Javascript
javascript跟随滚动效果插件代码(javascript Follow Plugin)
2013/08/03 Javascript
jquery 页面滚动到指定DIV实现代码
2013/09/25 Javascript
js变量、作用域及内存详解
2014/09/23 Javascript
从数据库读取数据后将其输出成html标签的三种方法
2014/10/13 Javascript
基于jQuery仿淘宝产品图片放大镜代码分享
2020/06/23 Javascript
浅谈js数组和splice的用法
2016/12/04 Javascript
根据Bootstrap Paginator改写的js分页插件
2016/12/25 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
electron + vue项目实现打印小票功能及实现代码
2018/11/25 Javascript
JavaScript实现图片的放大缩小及拖拽功能示例
2019/05/14 Javascript
微信小程序服务器日期格式化问题
2020/01/07 Javascript
Bootstrap实现前端登录页面带验证码功能完整示例
2020/03/26 Javascript
python轻松实现代码编码格式转换
2015/03/26 Python
Python的Django框架使用入门指引
2015/04/15 Python
python中split方法用法分析
2015/04/17 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
pymysql 开启调试模式的实现
2019/09/24 Python
tensorflow 只恢复部分模型参数的实例
2020/01/06 Python
Jupyter Notebook添加代码自动补全功能的实现
2021/01/07 Python
俄罗斯的精英皮具:Wittchen
2018/01/29 全球购物
以色列的身体护理及家居香薰品牌:Sabon NYC
2018/02/23 全球购物
好莱坞百老汇御用王牌美妆:Koh Gen Do 江原道
2018/04/03 全球购物
BLACKMORES澳洲官网:澳大利亚排名第一的保健品牌
2018/09/27 全球购物
美国牛仔品牌:True Religion
2018/11/16 全球购物
UNIX文件系统常用命令
2012/05/25 面试题
《美丽的田园》教学反思
2014/03/01 职场文书
总结表彰大会主持词
2014/03/26 职场文书
毕业实习自我鉴定范文2014
2014/09/26 职场文书
2014年施工员工作总结
2014/11/18 职场文书
丽江古城导游词
2015/02/03 职场文书
常用的MongoDB查询语句的示例代码
2021/07/25 MongoDB
Python音乐爬虫完美绕过反爬
2021/08/30 Python
十大最强格斗系宝可梦,超梦X仅排第十,第二最重格斗礼仪
2022/03/18 日漫