用Python实现一个爬取XX大学电费通知的小脚本

内容简要

   1分析网站

   2简单爬取

   3进阶自定义爬取

   4保存进数据库

学校基础设施太差,宿舍电量过低提醒虽然贴在楼下,但是作为低头一族,经常忘记看提醒导致宿舍酣战时突然黑屏,为了避免这种尴尬的场景以及强化PY学习,我决定制作一个简单的爬虫。

首先我通过学校的微信公众号找到了一个十分隐蔽的查低电量提醒网站。它的界面是这样的:

手机适应的页面当然在电脑上会有一些崩=。=,但是不要介意,我们要的是功能。下面是查询到的界面

虽然看起来low而且经常不更新,但是它至少能用。于是我决定用它来制作低电量提醒查询脚本。审查元素,我们可以发现

<form action="/houqin/store/findone.action" method="post" enctype="multipart/form-data" id="form22">
                      <input type="hidden" name="kindId" value="9">
      <div>
          <table style="width:100%;border-collapse:collapse;height:70px;border-collapse:collapse;">
              <tbody><tr>
                   <td style="width:30%;">
                       <table style="width:100%;border-collapse:collapse;">

                           <tbody><tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;宿舍区域</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                           <tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;楼号</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                           <tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;宿舍号</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                           <tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;截止时间</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                           <tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;剩余电量</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                           <tr style="width:100%;height:50px;">
                               <td style="padding-left:3px;">
                                   <font face="宋体" color="#4682B4" size="3"><strong>&nbsp;&nbsp;</strong></font>
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>

                       </tbody></table>
                   </td>
                   <td style="width:70%;">
                       <table style="width:100%;border-collapse:collapse;" id="taet"> 

                           <tbody><tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text0" id="text0" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">

                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                           <tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text1" id="text1" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                           <tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text2" id="text2" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                           <tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text3" id="text3" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                           <tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text4" id="text4" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                           <tr style="width:100%;height:50px;">
                               <td>
                                   <input type="text" name="search.text5" id="text5" value="" style="border: 2 solid #FAF0E6; width:80%;height:40px;font-size: 17px;font-weight: 800;color:#4682B4">
                               </td>
                           </tr>
                           <tr style="height:20px;"></tr>
                       </tbody></table>
                   </td>
               </tr>
               <tr style="height:40px;"></tr>
               <tr style="width:100%;height:70px;background:#FFFFFF;">
                   <td colspan="2" align="center">
                   <input type="button" onclick="subhdhp();" value="提交" style="width:80%;height:40px;background:#4682B4;color:#FFFFFF; font-size:17px;font-weight:900; border: 0px;">
                   </td>
               </tr>
          </tbody></table>

      </div>
  <br>
  <br><br>

</form>

完整表单信息

简化重要的部分,可以看出,这个表单有用的信息有如下代码:

<form action="/houqin/store/findone.action" method="post" enctype="multipart/form-data" id="form22">
  <input type="hidden" name="kindId" value="9">
    <div>
              <table >
            <tbody>
                                    <tr>
                                 <td >
              <table  id="taet">
                            <tbody><tr >
                                <td>
                                    <input type="text" name="search.text0" id="text0" value="">
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <input type="text" name="search.text1" id="text1" value="">
                                </td>
                            </tr>

                            <tr >
                                <td>
                                    <input type="text" name="search.text2" id="text2" value="">
                                </td>
                            </tr>

                            <tr>
                                <td>
                                    <input type="text" name="search.text3" id="text3" value="">
                                </td>
                            </tr>

                            <tr>
                               <td>
                                    <input type="text" name="search.text4" id="text4" value="">
                               </td>
                            </tr>
                            <tr></tr>
                            <tr>
                                <td>
                                    <input type="text" name="search.text5" id="text5" value="">
                                </td>
                            </tr>

                        </tbody></table>
                    </td>
                </tr>

                <tr>
                    <td colspan="2" align="center">
                   <input type="button" onclick="subhdhp();" value="提交">
                    </td>
                </tr>
           </tbody></table>
       </div></form>

简化版HTML

提取完以后感觉难度就降低了不少。但是只用填前3个空就能查询到。我觉得后几个空可能会设定一些防止爬取的障碍,我使用审查元素中自带的查询network功能看了一下。在一个post方法中我找到了如下数据:

------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="kindId"

9
------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text0"

北区
------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text1"

3
------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text2"

537
------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text3"

------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text4"

------WebKitFormBoundaryOJwEBCeqt5bb9jEZ
Content-Disposition: form-data; name="search.text5"

------WebKitFormBoundaryOJwEBCeqt5bb9jEZ--

Post 数据

这跟我之前见到的post格式不同,上网查了一下,这是一种叫做multipart/form-data格式的post,它能把post信息以二进制形式发送过去,所以还能用来传送文件。做个小脚本还能学到这样的新知识。阅历+1.

根据它的基本信息。我写了如下的代码来post并抓取得到的网页全内容

# -*- coding: utf-8 -*-

import urllib2
import urllib

url=‘http://hqsz.ouc.edu.cn/houqin/store/findone.action‘

boundary=‘---------------------------12174501422663‘ #分隔符
data = []
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="kindId" ‘)
data.append(‘‘)
data.append(‘9 ‘ )
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text0" ‘)
data.append(‘‘)
data.append(‘北区 ‘)
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text1" ‘)
data.append(‘‘)
data.append(‘3 ‘)
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text2" ‘)
data.append(‘‘)
data.append(‘537 ‘)
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text3" ‘)
data.append(‘‘)
data.append(‘‘)
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text4" ‘)
data.append(‘‘)
data.append(‘‘)
data.append(‘--‘+boundary)
data.append(‘Content-Disposition: form-data; name="search.text5" ‘)
data.append(‘‘)
data.append(‘‘)
data.append(‘--‘+boundary+‘--‘)
data.append(‘‘)
httpbody=‘\r\n‘.join(data)
print type(httpbody)
content_type=‘multipart/form-data; boundary=%s‘ %boundary
print content_type
req = urllib2.Request(url,httpbody)
req.add_header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.add_header("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:46.0) Gecko/20100101 Firefox/46.0")
req.add_header("Referer","http://hqsz.ouc.edu.cn/houqin/store/findmessage.action?kindId=9")
req.add_header("Content-Type", content_type )
req.add_header("Accept-Language","zh-CN,en-US;q=0.7,en;q=0.3")
req.add_header("Accept-Encoding","gzip, deflate")
req.add_header("Connection","keep_alive")
response = urllib2.urlopen(req)
html = response.read()
print html

抓取网页

这段代码分为2个部分,前半部分是表单生成。后半部分是模拟浏览器头,虽然这个网站并不会检测,但是为了学习还是要写这一部分强化记忆。对于表单生成这部分,我得到了如下的公式:对于multipart/form-data这样的信息一般可以用如下格式:

这其中的data.append(‘‘)是必加的,图省事省略掉就错了。

这样的代码只能针对一个人的,不能由用户输入,这样感觉很不好,于是我选择加上用户输入。先把以上函数封装成一个函数Search_e(eara,house,room);

之后在py中调用这个函数就行了,代码如下:

# -*- coding: utf-8 -*-
# encoding: utf-8
import urllib2,re
import urllib

def Search_e(eara,house,room):
    #post的目标地址
    url=‘http://hqsz.ouc.edu.cn/houqin/store/findone.action‘
    #设置post的数据
    boundary=‘---------------------------12174501422663‘ #分隔符
    data = []
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="kindId"‘)
    data.append(‘‘)
    data.append(‘9‘ )
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text0"‘)
    data.append(‘‘)
    data.append(eara)
    #查询房间所在区域
    #data.append(‘北区‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text1"‘)
    data.append(‘‘)
    #查询房间所在的楼号
    data.append(house)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text2"‘)
    data.append(‘‘)
    #查询房间的房间号
    data.append(room)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text3"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text4"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text5"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary+‘--‘)
    data.append(‘‘)
    httpbody=‘\r\n‘.join(data)
    #以上部分就是查询信息的表单
    content_type=‘multipart/form-data; boundary=%s‘ %boundary
    #print data    #检验表单数据
    req = urllib2.Request(url,httpbody)
    req.add_header("Content-Type", content_type )
    req.add_header("Accept-Language","zh-CN,en-US;q=0.7,en;q=0.3")
    req.add_header("Accept-Encoding","gzip, deflate")
    #req.add_header("Connection","keep_alive")
    response = urllib2.urlopen(req)
    html = response.read()
    unicodePage=html.decode("utf-8")
    pattern=ur"<strong>([\s\S]*?)<\/strong>"
    result=re.findall(pattern,unicodePage,re.S)
    try:
        if(result[11]):
            print u"剩余电量",result[11],u"请及时交电费"
    except:
        print u"电量充足"

eara=raw_input("请输入区域(北区,东区,南区):")
eara=eara.decode(‘gbk‘).encode(‘utf-8‘)  #将输入的Gbk字符转化为utf-8字符
house=raw_input("请输入楼号(例如1号楼:1):")
room=raw_input("请输入房间号(例如110房间:110):")
Search_e(eara,house,room)

用户自定义友好

光查询还不能满足我,我还想知道最近的用电情况,我决定把他们保存在数据库中进行分析。

于是我更换了如下代码,

# -*- coding: utf-8 -*-
# encoding:utf-8
import urllib2,re
import urllib
import MySQLdb as db

def Search_e(eara,house,room):
    #post的目标地址
    url=‘http://hqsz.ouc.edu.cn/houqin/store/findone.action‘
    #设置post的数据
    boundary=‘---------------------------12174501422663‘ #分隔符
    data = []
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="kindId"‘)
    data.append(‘‘)
    data.append(‘9‘ )
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text0"‘)
    data.append(‘‘)
    #data.append(eara)
    #查询房间所在区域
    data.append(‘北区‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text1"‘)
    data.append(‘‘)
    #查询房间所在的楼号
    data.append(house)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text2"‘)
    data.append(‘‘)
    #查询房间的房间号
    data.append(room)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text3"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text4"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary)
    data.append(‘Content-Disposition: form-data; name="search.text5"‘)
    data.append(‘‘)
    data.append(‘‘)
    data.append(‘--‘+boundary+‘--‘)
    data.append(‘‘)
    httpbody=‘\r\n‘.join(data)
    #以上部分就是查询信息的表单
    content_type=‘multipart/form-data; boundary=%s‘ %boundary
    #print data    #检验表单数据
    req = urllib2.Request(url,httpbody)
    req.add_header("Content-Type", content_type )
    req.add_header("Accept-Language","zh-CN,en-US;q=0.7,en;q=0.3")
    req.add_header("Accept-Encoding","gzip, deflate")
    #req.add_header("Connection","keep_alive")
    response = urllib2.urlopen(req)
    html = response.read()
    unicodePage=html.decode("utf-8")
    pattern=ur"<strong>([\s\S]*?)<\/strong>"
    result=re.findall(pattern,unicodePage,re.S)
    try:
        return result[11]
    except:
        return ‘20.0‘

connection = db.connect(host=‘localhost‘,user=‘root‘,passwd=‘root‘,db=‘oucect‘,port=3306,init_command=‘set names utf8‘)
cursor = connection.cursor()
cursor.execute("select * from rooms");
result = cursor.fetchall()
cursor.close()
connection.close()
print result
for item in result:
    aera=item[3]
    house = item[1]
    room = item[2]
    num=Search_e(aera,house,room)
    connection = db.connect(host=‘localhost‘,user=‘root‘,passwd=‘root‘,db=‘oucect‘,port=3306,init_command=‘set names utf8‘)
    cursor = connection.cursor()
    cursor.execute("update rooms set ect = "+num+" where id="+str(item[0]));
    connection.commit();
    cursor.close();
    connection.close();

保存数据库版本

现在这样就可以保存进数据库了,但是这个网站几乎是7-5天更新一次,我现在还不会计划任务爬取网页进行分析,我要学习的还有很多,现在一个用C#写出来的自动发邮件的小程序已经完成。我相信我就能够一点一点变成大神的。

时间: 2024-08-24 15:52:33

用Python实现一个爬取XX大学电费通知的小脚本的相关文章

Python爬虫——定向爬取“中国大学排名网”

内容整理自中国大学MOOC——北京理工大学-蒿天-Python网络爬虫与信息提取 相关实战章节 我们预爬取的url如下 http://www.zuihaodaxue.cn/zuihaodaxuepaiming2019.html 网页节选 在浏览器中读取网页源代码 可以 发现表格数据信息是直接写入HTML页面信息中,所以我们可以直接采取定向爬虫操作. 我们的整体设计思路如下: 1.从网络上获取大学排名网络内容 2.提取网页内容中信息到合适的数据结构 3.利用数据结构展示并输出结果 仔细观察可以发现

python爬取中国大学排名

教程来自:[Python网络爬虫与信息提取].MOOC. 北京理工大学 目标:爬取最好大学网前50名大学 代码如下: import requests from bs4 import BeautifulSoup import bs4 def getHTMLText(url): try: r = requests.get(url,timeout = 30) r.raise_for_status() r.encoding = r.apparent_encoding return r.text exce

[Python爬虫] Selenium爬取新浪微博客户端用户信息、热点话题及评论 (上)

一. 文章介绍 前一篇文章"[python爬虫] Selenium爬取新浪微博内容及用户信息"简单讲述了如何爬取新浪微博手机端用户信息和微博信息. 用户信息:包括用户ID.用户名.微博数.粉丝数.关注数等. 微博信息:包括转发或原创.点赞数.转发数.评论数.发布时间.微博内容等. 它主要通过从文本txt中读取用户id,通过"URL+用户ID" 访问个人网站,如柳岩: http://weibo.cn/guangxianliuya 因为手机端数据相对精简简单,所以采用输

[python学习] 简单爬取维基百科程序语言消息盒

文章主要讲述如何通过Python爬取维基百科的消息盒(Infobox),主要是通过正则表达式和urllib实现:后面的文章可能会讲述通过BeautifulSoup实现爬取网页知识.由于这方面的文章还是较少,希望提供一些思想和方法对大家有所帮助.如果有错误或不足之处,欢迎之处:如果你只想知道该篇文章最终代码,建议直接阅读第5部分及运行截图. 一. 维基百科和Infobox 你可能会疑惑Infobox究竟是个什么东西呢?下面简单介绍. 维基百科作为目前规模最大和增长最快的开放式的在线百科系统,其典型

[python] 常用正则表达式爬取网页信息及分析HTML标签总结【转】

[python] 常用正则表达式爬取网页信息及分析HTML标签总结 转http://blog.csdn.net/Eastmount/article/details/51082253 标签: pythonpython爬虫正则表达式html知识总结 2016-04-07 06:13 3615人阅读 评论(4) 收藏 举报  分类: Python爬虫(23)  Python基础知识(17)  版权声明:本文为博主原创文章,转载请注明CSDN博客源地址!共同学习,一起进步~ 这篇文章主要是介绍Pytho

[Python爬虫] Selenium爬取新浪微博移动端热点话题及评论 (下)

这篇文章主要讲述了使用python+selenium爬取新浪微博的热点话题和评论信息.其中使用该爬虫的缺点是效率极低,傻瓜式的爬虫,不能并行执行等,但是它的优点是采用分析DOM树结构分析网页源码并进行信息爬取,同时它可以通过浏览器进行爬取中间过程的演示及验证码的输入.这篇文章对爬虫的详细过程就不再论述了,主要是提供可运行的代码和运行截图即可.希望文章对你有所帮助吧~ 参考文章 [python爬虫] Selenium爬取新浪微博内容及用户信息 [Python爬虫] Selenium爬取新浪微博客户

Python爬虫入门 | 爬取豆瓣电影信息

这是一个适用于小白的Python爬虫免费教学课程,只有7节,让零基础的你初步了解爬虫,跟着课程内容能自己爬取资源.看着文章,打开电脑动手实践,平均45分钟就能学完一节,如果你愿意,今天内你就可以迈入爬虫的大门啦~好啦,正式开始我们的第二节课<爬取豆瓣电影信息>吧!啦啦哩啦啦,都看黑板~1. 爬虫原理1.1 爬虫基本原理听了那么多的爬虫,到底什么是爬虫?爬虫又是如何工作的呢?我们先从"爬虫原理"说起.爬虫又称为网页蜘蛛,是一种程序或脚本.但重点在于:它能够按照一定的规则,自动

如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)

前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往下继续深入. 一.代码实现 1.修改Scrapy项目中的items.py文件.我们需要获取的数据是朋友圈和发布日期,因此在这里定义好日期和动态两个属性,如下图所示. 2.修改实现爬虫逻辑的主文件moment.py,首先要导入模块,尤其是要主要将items.py中的WeixinMomentItem类导入进来,这点要特别小心别被遗漏了.之后修改start_requests方

爬取耶鲁大学公开课

耶鲁大学(Yale University)是一所坐落于美国康涅狄格州纽黑文的私立研究型大学,创于1701年,初名“大学学院”(Collegiate School),是全美历史第三悠久的高等学府,亦为常春藤盟校成员之一.该校教授阵容.学术创新.课程设置和场馆设施等方面堪称一流.除了研究生课程之外,耶鲁同时也非常注重本科生教育.在各个大学排名榜单中,都一直名列前茅. 所以,我们今天的目标是爬取耶鲁大学公开课信息,并将它们加以保存. 首先,我们打开耶鲁大学公开课的首页进行分析.可以看到,在表格中有着许