python&MongoDB爬取图书馆借阅记录


Posted in Python onFebruary 05, 2016

直接上需求和代码
首先是需要爬取的链接和网页:http://211.81.31.34/uhtbin/cgisirsi/x/0/0/57/49?user_id=LIBSCI_ENGI&password=LIBSC

python&MongoDB爬取图书馆借阅记录

登陆进去之后进入我的账号——借阅、预约及申请记录——借阅历史就可以看到所要爬取的内容

python&MongoDB爬取图书馆借阅记录

然后将借阅历史中的题名、著者、借阅日期、归还日期、索书号存入Mongodb数据库中,以上便是这次爬虫的需求。

下面开始:

各软件版本为:

  • python 2.7.11
  • MongoDb 3.2.1
  • Pycharm 5.0.4
  • MongoDb Management Studio 1.9.3
  • 360极速浏览器 懒得查了

一、登陆模块
python中的登陆一般都是用urllib和urllib2这两个模块,首先我们要查看网页的源代码:
<form name="loginform" method="post" action="/uhtbin/cgisirsi/?ps=nPdFje4RP9/理工大学馆/125620449/303">
<!--  Copyright (c) 2004, Sirsi Corporation - myProfile login or view myFavorites -->
<!--  Copyright (c) 1998 - 2003, Sirsi Corporation - Sets the default values for USER_ID, ALT_ID, and PIN prompts. - The USER_ID, ALT_ID, and PIN page variables will be returned. -->

<!-- If the user has not logged in, first try to default to the ID based on the IP address - the $UO and $Uf will be set.  If that fails, then default to the IDs in the config file. If the user has already logged in, default to the logged in user's IDs, unless the user is a shared login. -->

 

      <!-- only user ID is used if both on -->
        <div class="user_name">
            <label for="user_id">借阅证号码:</label>
            <input class="user_name_input" type="text" name="user_id" id="user_id"  maxlength="20" value=""/>
        </div>
   
    
        <div class="password">
            <label for="password">个人密码:</label>
            <input class="password_input" type="password" name="password" id="password"  maxlength="20" value=""/>
        </div> 
   
    
    <input type="submit" value="用户登录" class="login_button"/>
查找网页中的form表单中的action,方法为post,但是随后我们发现,该网页中的action地址不是一定的,是随机变化的,刷新一下就变成了下面这样子的:
 <form name="loginform" method="post" action="/uhtbin/cgisirsi/?ps=1Nimt5K1Lt/理工大学馆/202330426/303">
我们可以看到/?ps到/之间的字符串是随机变化的(加粗部分),于是我们需要用到另一个模块——BeautifulSoup实时获取该链接:
url = "http://211.81.31.34/uhtbin/cgisirsi/x/0/0/57/49?user_id=LIBSCI_ENGI&password=LIBSC"
   res = urllib2.urlopen(url).read()
    soup = BeautifulSoup(res, "html.parser")
login_url = "http://211.81.31.34" + soup.findAll("form")[1]['action'].encode("utf8")
之后就可以正常使用urllib和urllib来模拟登陆了,下面列举一下BeautifulSoup的常用方法,之后的HTML解析需要:

1.soup.contents 该属性可以将tag的子节点以列表的方式输出

2.soup.children 通过tag的.children生成器,可以对tag的子节点进行循环

3.soup.parent 获取某个元素的父节点

4.soup.find_all(name,attrs,recursive,text,**kwargs) 搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件

5.soup.find_all("a",class="xx") 按CSS搜索

6.find(name,attrs,recursive,text,**kwargs) 可以通过limit和find_all区分开

二、解析所获得的HTML

先看看需求中的HTML的特点:
<tbody id="tblSuspensions">
<!-- OCLN changed Listcode to Le to support charge history -->
     <!-- SIRSI_List Listcode="LN" -->

     <tr>
       <td class="accountstyle" align="left">
          <!-- SIRSI_Conditional IF List_DC_Exists="IB" AND NOT List_DC_Comp="IB^" -->
<!-- Start title here -->
 <!-- Title -->
            做人要低调,说话要幽默 孙郡铠编著
        </td>
       <td class="accountstyle author" align="left">
          <!-- Author -->
            孙郡铠 编著
        </td>
       <td class="accountstyle due_date" align="center">
          <!-- Date Charged -->
            2015/9/10,16:16
       </td>
        <td class="accountstyle due_date" align="left">
        <!-- Date Returned -->
            2015/9/23,15:15
        </td>

        <td class="accountstyle author" align="center">
          <!-- Call Number -->
            B821-49/S65
        </td>

      </tr>

     <tr>
       <td class="accountstyle" align="left">
          <!-- SIRSI_Conditional IF List_DC_Exists="IB" AND NOT List_DC_Comp="IB^" -->
<!-- Start title here -->
 <!-- Title -->
            我用一生去寻找 潘石屹的人生哲学 潘石屹著
        </td>
       <td class="accountstyle author" align="left">
          <!-- Author -->
            潘石屹, 1963- 著
        </td>
       <td class="accountstyle due_date" align="center">
          <!-- Date Charged -->
            2015/9/10,16:16
       </td>
        <td class="accountstyle due_date" align="left">
        <!-- Date Returned -->
            2015/9/25,15:23
        </td>

        <td class="accountstyle author" align="center">
          <!-- Call Number -->
            B821-49/P89
        </td>

      </tr>
由所有代码,注意这行:

<tbody id="tblSuspensions">
该标签表示下面的内容将是借阅书籍的相关信息,我们采用遍历该网页所有子节点的方法获得id="tblSuspensions"的内容:
   for i, k in enumerate(BeautifulSoup(detail, "html.parser").find(id='tblSuspensions').children):
     # print i,k
        if isinstance(k, element.Tag):
             bookhtml.append(k)
                # print type(k)
三、提取所需要的内容

这一步比较简单,bs4中的BeautifulSoup可以轻易的提取:
for i in bookhtml:
                # p
                # rint i
                name = i.find(class_="accountstyle").getText()
                author = i.find(class_="accountstyle author", align="left").getText()
                Date_Charged = i.find(class_="accountstyle due_date", align="center").getText()
                Date_Returned = i.find(class_="accountstyle due_date", align="left").getText()
                bookid = i.find(class_="accountstyle author", align="center").getText()
                bookinfo.append(
                    [name.strip(), author.strip(), Date_Charged.strip(), Date_Returned.strip(), bookid.strip()])
这一步采用getText()的方法将text中内容提取出来;strip()方法是去掉前后空格,同时可以保留之间的空格,比如:s="   a a  ",使用s.strip()之后即为"a a"

四、连接数据库
据说NoSQL以后会很流行,随后采用了Mongodb数据库图图新鲜,结果一折腾真是烦,具体安装方法在上一篇日记中记载了。
1.导入python连接Mongodb的模块

import pymongo
2.创建python和Mongodb的链接:
# connection database
conn = pymongo.MongoClient("mongodb://root:root@localhost:27017")
db = conn.book
collection = db.book
3.将获得的内容保存到数据库:
user = {"_id": xuehao_ben,
                        "Bookname": name.strip(),
                        "Author": author.strip(),
                        "Rent_Day": Date_Charged.strip(),
                        "Return_Day": Date_Returned.strip()}
                j += 1
                collection.insert(user)
上面基本完成了,但是爬虫做到这个没有意义,重点在下面

五、获取全校学生的借阅记录

我们学校的图书馆的密码都是一样的,应该没有人闲得无聊改密码,甚至没有人用过这个网站去查询自己的借阅记录,所以,做个循环,就可以轻易的获取到全校的借阅记录了,然后并没有那么简单,str(0001)强制将int变成string,但是在cmd的python中是报错的(在1位置),在pycharm前面三个0是忽略的,只能用傻瓜式的四个for循环了。好了,下面是所有代码:
# encoding=utf8
import urllib2
import urllib
import pymongo
import socket

from bs4 import BeautifulSoup
from bs4 import element

# connection database
conn = pymongo.MongoClient("mongodb://root:root@localhost:27017")
db = conn.book
collection = db.book

# 循环开始
def xunhuan(xuehao):
    try:
        socket.setdefaulttimeout(60)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("127.0.0.1", 80))
        url = "http://211.81.31.34/uhtbin/cgisirsi/x/0/0/57/49?user_id=LIBSCI_ENGI&password=LIBSC"
        res = urllib2.urlopen(url).read()
        soup = BeautifulSoup(res, "html.parser")
        login_url = "http://211.81.31.34" + soup.findAll("form")[1]['action'].encode("utf8")
        params = {
            "user_id": "账号前缀你猜你猜" + xuehao,
            "password": "密码你猜猜"
        }
        print params
        params = urllib.urlencode(params)
        req = urllib2.Request(login_url, params)
        lianjie = urllib2.urlopen(req)
        # print lianjie
        jieyue_res = lianjie.read()
        # print jieyue_res     首页的HTML代码
        houmian = BeautifulSoup(jieyue_res, "html.parser").find_all('a', class_='rootbar')[1]['href']
        # print houmian
        houmian = urllib.quote(houmian.encode('utf8'))
        url_myaccount = "http://211.81.31.34" + houmian
        # print url_myaccount
        # print urllib.urlencode(BeautifulSoup(jieyue_res, "html.parser").find_all('a',class_ = 'rootbar')[0]['href'])

        lianjie2 = urllib.urlopen(url_myaccount)
        myaccounthtml = lianjie2.read()
        detail_url = ''
        # print (BeautifulSoup(myaccounthtml).find_all('ul',class_='gatelist_table')[0]).children
        print "连接完成,开始爬取数据"
        for i in (BeautifulSoup(myaccounthtml, "html.parser").find_all('ul', class_='gatelist_table')[0]).children:
            if isinstance(i, element.NavigableString):
                continue
            for ii in i.children:
                detail_url = ii['href']
            break
        detail_url = "http://211.81.31.34" + urllib.quote(detail_url.encode('utf8'))
        detail = urllib.urlopen(detail_url).read()
        # print detail
        bookhtml = []
        bookinfo = []

        # 解决没有借书
        try:
            for i, k in enumerate(BeautifulSoup(detail, "html.parser").find(id='tblSuspensions').children):
                # print i,k
                if isinstance(k, element.Tag):
                    bookhtml.append(k)
                    # print type(k)
            print "look here!!!"
            j = 1
            for i in bookhtml:
                # p
                # rint i
                name = i.find(class_="accountstyle").getText()
                author = i.find(class_="accountstyle author", align="left").getText()
                Date_Charged = i.find(class_="accountstyle due_date", align="center").getText()
                Date_Returned = i.find(class_="accountstyle due_date", align="left").getText()
                bookid = i.find(class_="accountstyle author", align="center").getText()
                bookinfo.append(
                    [name.strip(), author.strip(), Date_Charged.strip(), Date_Returned.strip(), bookid.strip()])
                xuehao_ben = str(xuehao) + str("_") + str(j)
                user = {"_id": xuehao_ben,
                        "Bookname": name.strip(),
                        "Author": author.strip(),
                        "Rent_Day": Date_Charged.strip(),
                        "Return_Day": Date_Returned.strip()}
                j += 1
                collection.insert(user)
        except Exception, ee:
            print ee
            print "此人没有借过书"
            user = {"_id": xuehao,
                    "Bookname": "此人",
                    "Author": "没有",
                    "Rent_Day": "借过",
                    "Return_Day": "书"}
            collection.insert(user)

        print "********" + str(xuehao) + "_Finish"+"**********"
    except Exception, e:
        s.close()
        print e
        print "socket超时,重新运行"
        xunhuan(xuehao)

# with contextlib.closing(urllib.urlopen(req)) as A:
#    print A
#   print xuehao
# print req

for i1 in range(0, 6):
    for i2 in range(0, 9):
        for i3 in range(0, 9):
            for i4 in range(0, 9):
                xueha = str(i1) + str(i2) + str(i3) + str(i4)
                chushi = '0000'
                if chushi == xueha:
                    print "=======爬虫开始=========="
                else:
                    print xueha + "begin"
                    xunhuan(xueha)

conn.close()
print "End!!!"
下面是Mongodb Management Studio的显示内容(部分):

 python&amp;MongoDB爬取图书馆借阅记录

 

总结:这次爬虫遇到了很多问题,问了很多人,但是最终效果还不是很理想,虽然用了try except语句,但是还是会报错10060,连接超时(我只能质疑学校的服务器了TT),还有就是,你可以看到数据库中列的顺序不一样=。=这个我暂时未理解,希望大家可以给出解决方法。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Python 相关文章推荐
python socket 超时设置 errno 10054
Jul 01 Python
浅谈Python 字符串格式化输出(format/printf)
Jul 21 Python
Python实现八大排序算法
Aug 13 Python
python爬取网页内容转换为PDF文件
Jul 28 Python
对Tensorflow中的变量初始化函数详解
Jul 27 Python
python按时间排序目录下的文件实现方法
Oct 17 Python
python绘制已知点的坐标的直线实例
Jul 04 Python
python中for循环把字符串或者字典添加到列表的方法
Jul 20 Python
浅谈PyTorch的可重复性问题(如何使实验结果可复现)
Feb 20 Python
详解Python中的文件操作
Jan 14 Python
python编写五子棋游戏
May 25 Python
Pygame游戏开发之太空射击实战敌人精灵篇
Aug 05 Python
Python中常用操作字符串的函数与方法总结
Feb 04 #Python
Python中的字符串类型基本知识学习教程
Feb 04 #Python
Python的math模块中的常用数学函数整理
Feb 04 #Python
详解Python编程中基本的数学计算使用
Feb 04 #Python
Python连接mysql数据库的正确姿势
Feb 03 #Python
Python内建数据结构详解
Feb 03 #Python
Python解析树及树的遍历
Feb 03 #Python
You might like
简单解决新浪SAE无法上传文件的问题
2015/05/13 PHP
yii2.0实现pathinfo的形式访问的配置方法
2016/04/06 PHP
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
jquery解析json格式数据的方法(对象、字符串)
2015/11/24 Javascript
js代码延迟一定时间后执行一个函数的实例
2017/02/15 Javascript
微信小程序动态的加载数据实例代码
2017/04/14 Javascript
详解vue axios中文文档
2017/09/12 Javascript
浅谈vue中.vue文件解析流程
2018/04/24 Javascript
详解如何在vue-cli中使用vuex
2018/08/07 Javascript
JS浅拷贝和深拷贝原理与实现方法分析
2019/02/28 Javascript
JS实现简单移动端鼠标拖拽
2020/07/23 Javascript
解决Ant Design Modal内嵌Form表单initialValue值不动态更新问题
2020/10/29 Javascript
详解JavaScript中的this指向问题
2021/02/05 Javascript
[01:15:18]2014 DOTA2国际邀请赛中国区预选赛 LGD VS Speed Gaming.cn
2014/05/22 DOTA
[01:57]2016完美“圣”典风云人物:国士无双专访
2016/12/04 DOTA
[52:41]OG vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/20 DOTA
python3使用urllib示例取googletranslate(谷歌翻译)
2014/01/23 Python
HTML中使用python屏蔽一些基本功能的方法
2017/07/07 Python
CentOS 6.5中安装Python 3.6.2的方法步骤
2017/12/03 Python
django模板语法学习之include示例详解
2017/12/17 Python
Python机器学习k-近邻算法(K Nearest Neighbor)实例详解
2018/06/25 Python
Python OS模块实例详解
2019/04/15 Python
python递归法解决棋盘分割问题
2019/07/17 Python
利用keras加载训练好的.H5文件,并实现预测图片
2020/01/24 Python
django model的update时auto_now不被更新的原因及解决方式
2020/04/01 Python
Python安装并操作redis实现流程详解
2020/10/13 Python
纯CSS和jQuery实现的在页面顶部显示的进度条效果2例(仿手机浏览器进度条效果)
2014/04/16 HTML / CSS
一款基于css3麻将筛子3D翻转特效的实例教程
2014/12/31 HTML / CSS
日语专业毕业生自荐信
2013/11/11 职场文书
高中校园广播稿
2014/01/11 职场文书
简历的自我评价
2014/02/03 职场文书
致铅球运动员加油稿
2014/02/13 职场文书
厨房领班竞聘演讲稿
2014/04/23 职场文书
招标承诺书
2014/08/30 职场文书
运动员入场前导词
2015/07/20 职场文书
校友会致辞
2015/07/30 职场文书