• python动态网页爬取——四六级成绩批量爬取


    需求:

      四六级成绩查询网站我所知道的有两个:学信网(http://www.chsi.com.cn/cet/)和99宿舍(http://cet.99sushe.com/),这两个网站采用的都是动态网页。我使用的是学信网,好了,网站截图如下:

                                                            

    网站的代码如下:

     1 <form method="get" name="form1" id="form1" action="/cet/query">
     2 
     3 <table border="0" align="center" cellpadding="0" cellspacing="0">
     4 <tr><td align="right">准考证号:</td><td align="left"><input name="zkzh" value="112008000463141" id="zkzh" type="text" size="18" maxlength="15" class="input_text input_t_l" /></td>
     5   <td align="left" class="font12 color666">请输入15位准考证号</td>
     6 </tr>
     7 <tr><td align="right">姓名:</td><td align="left"><input name="xm" value="啊啊" id="xm" type="text" size="18" maxlength="50" class="input_text input_t_l" /></td>
     8   <td align="left" class="font12 color666">姓名超过3个字,可只输入前3个</td>
     9 </tr>
    10 
    11 <tr><td align="center">&nbsp;</td>
    12   <td colspan="2" align="left"><input type="submit" id="submitCET" class="btn_blue" value="查询" /></td>
    13   </tr>
    14 </table>
    15 </form>

    由图中可以看出表单提交的链接为/cet/query,即:http://www.chsi.com.cn/cet/query,好了,填写表单和结果如下:

                              

    但是,点击查看源代码之后发现,没有成绩,即代码仍是上面那个,之后按F12查看代码:

     1 <TBODY><TR>
     2 <TH>姓名:</TH>
     3 <TD>XXXX</TD></TR>
     4 <TR>
     5 <TH>学校:</TH>
     6 <TD>XXXXXX</TD></TR>
     7 <TR>
     8 <TH>考试类别:</TH>
     9 <TD>英语四级</TD></TR>
    10 <TR>
    11 <TH>准考证号:</TH>
    12 <TD>120135151100101</TD></TR>
    13 <TR>
    14 <TH>考试时间:</TH>
    15 <TD>2015年06月</TD></TR>总分:</TH><TD class=fontBold vAlign="top"><SPAN class=colorRed>403 </SPAN><BR><SPAN class=color666>听力:</SPAN> 132 <BR><SPAN class=color666>阅读:</SPAN> 147 <BR><SPAN class=color666>写作与翻译:</SPAN> 124 </TD></TR>

    该代码显示了成绩,可以知道,该网站使用的是动态网页,用的JavaScript或者Ajax.js还是其他的我就不知道了0.0。上面为需求。

      前言:使用过BeautifulSoup爬取过,但是BeautifulSoup是爬取不了动态网页的,上各种论坛找各种资料,用了n种东西,scapy,pyqt等等,走了真心不少弯路,不是不行,应该是我不会用,最终用了selenium和phantomjs,这两个应该也是目前最流行的爬虫模块了吧。

    一、导入selenium和phantomjs

      

    1 from selenium import webdriver
    2 
    3 driver = webdriver.PhantomJS(executable_path='D:phantomjs-2.1.1-windowsphantomjs.exe')
    4 driver.get(url)
    5 driver.find_element_by_id('zkzh').send_keys(i)
    6 driver.find_element_by_id('xm').send_keys(xm)
    7 driver.find_elements_by_tag_name('form')[1].submit()

      代码说明:

      3.selenium可以加载很多驱动,比如Chrome、FireFox等,这里需要有这两个浏览器和驱动才行,折腾了一下,网上说Phantomjs是较好的了

      5、6、7分别是准考证号,姓名和提交

    二、字符处理

    提交之后就可以直接查找了:

    1 print driver.find_element_by_xpath("//tr[3]/td[1]").text
    2 print driver.find_element_by_xpath("//tr[6]/td[1]").text

      代码说明:

      1.查看姓名

      2.查看分数及其具体成绩

      打印之后为:

    姓名
    403
    听力
    132
    阅读
    147
    写作
    142

      之后要对分数进行字符串处理,选取各部分的数字,这里我们采用re模块:

    1 import re
    2 m = re.findall(r'(w*[0-9]+)w*', chuli2)

      其中m是数组,输出的是["403","132","147","142"]

    三、数据库

      我们学校也不知说很渣还是人性化,反正公布了全校的四六级准考证号,当然,是excel的,需要导入mysql数据库,打开Excel之后,我发现微软大法和Oracle真是牛逼啊,Excel365居然有mysql workbench连接部分

     数据库代码如下:

     1 import MySQLdb
     2 
     3 conn = MySQLdb.Connect(host='localhost', user='root', passwd='root', db='cet', port=3306, charset='utf8')
     4 cur = conn.cursor()
     5 curr = conn.cursor()
     6 cur.execute("select name from cet.cet where zkzh=(%s)" % i)
     7 xm = cur.fetchone()[0]
     8 print "Name is " + xm
     9 sqltxt = "update cet.cet set leibie=(%s),zongfen=(%s),tingli=(%s),yuedu=(%s),xiezuo=(%s) WHERE zkzh=(%s)" % (
    10             ss, m[0], m[1], m[2], m[3], i)
    11 cur.execute(sqltxt)
    12 conn.commit()
    13 cur.close()
    14 conn.close()

      代码说明:

      3.python连接数据库代码

      6.连接数据库取得姓名部分

      9.这行我好无语啊,使用‘“+ss+”’这样的写法一直报错,最终找了半天资料,这个写法我不太喜欢,但是凑合着用吧。

      12.记得一定要提交事务!!!commit()!!!不然是没有效果的

    四、使用代理服务器(保留以后写)

      运行了一段时间之后,大概抓了几百人的吧,然后就出现要求验证码了,解决办法只能处理验证码或者使用代理服务器了,这部分继续加强学习再弄出来了↖(^ω^)↗

    五、源代码和效果

     1 # encoding=utf8
     2 
     3 import MySQLdb
     4 import re
     5 import time
     6 
     7 from selenium import webdriver
     8 
     9 # connect mysql,get zkxh and xm
    10 conn = MySQLdb.Connect(host='localhost', user='root', passwd='root', db='cet', port=3306, charset='utf8')
    11 cur = conn.cursor()
    12 curr = conn.cursor()
    13 url = 'http://www.chsi.com.cn/cet/query'
    14 
    15 
    16 def kaishi(i):
    17     print i,
    18     print " start"
    19     try:
    20         cur.execute("select name from cet.cet where zkzh=(%s)" % i)
    21         xm = cur.fetchone()[0]
    22         print "Name is " + xm
    23         driver = webdriver.PhantomJS(executable_path='D:phantomjs-2.1.1-windowsphantomjs.exe')
    24         driver.get(url)
    25         driver.find_element_by_id('zkzh').send_keys(i)
    26         driver.find_element_by_id('xm').send_keys(xm)
    27         driver.find_elements_by_tag_name('form')[1].submit()
    28         driver.set_page_load_timeout(10)
    29         leibie = driver.find_element_by_xpath("//tr[3]/td[1]").text
    30         leibie2 = str(leibie.encode("utf-8"))
    31         ss = ""
    32         if leibie2.decode("utf-8") == '英语四级'.decode("utf-8"):
    33             ss = 4
    34         else:
    35             ss = 6
    36         # zongfen = driver.find_element_by_xpath("//tr[6]/th[1]").text
    37         # print zongfen
    38         # print "===="
    39         chuli = driver.find_element_by_xpath("//tr[6]/td[1]").text
    40         print chuli
    41         chuli2 = str(chuli.encode("utf-8"))
    42         m = re.findall(r'(w*[0-9]+)w*', chuli2)
    43         sqltxt = "update cet.cet set leibie=(%s),zongfen=(%s),tingli=(%s),yuedu=(%s),xiezuo=(%s) WHERE zkzh=(%s)" % (
    44             ss, m[0], m[1], m[2], m[3], i)
    45         cur.execute(sqltxt)
    46         conn.commit()
    47         print str(i) + " finish"
    48     except Exception, e:
    49         print e
    50         driver.close()
    51         time.sleep(10)
    52         kaishi(i)
    53 
    54 
    55 # for j1 in range(1201351511001, 1201351512154):
    56 for j1 in range(1201351511007, 1201351512154):
    57     for j2 in range(0, 3):
    58         for j3 in range(0, 10):
    59             j = str(j1) + str(j2) + str(j3)
    60             if str(j2) + str(j3) == "00":
    61                 print "0.0"
    62             elif str(j2) + str(j3) == "29":
    63                 kaishi(str(j1) + str(j2) + str(j3))
    64                 j4 = str(j1) + "30"
    65                 kaishi(j4)
    66             else:
    67                 kaishi(j)
    68 print "END!!!"
    69 cur.close()
    70 conn.close()

    参考资料:

    1.http://my.oschina.net/u/2420420/blog/489205?fromerr=MX68uajh

    2.http://www.cnblogs.com/hearzeus/p/5157016.html

    总结python的字符串处理细节真的很重要,动不动就输出错误,还有IDE的编码不一样,记得还有个系统编码,字符编码,环境编码,数据库编码等等都要一致!!!

    ps后记:1.这几天别人各种同学聚会,然而,自己也总是那么“幸运”,中学所碰到的班级对外特活跃特团结的样子,但是初中高中毕业那么久了,聚会是几乎没有过。。。。昨晚梦见了那些人那些事,也不知道他们怎么样了。昨天有一篇新闻报道了一大学一宿舍毕业20年,年年聚会的那样子真好。

    2.对于爱情的烦恼,莫过于明明很喜欢却发现自己和她完全不是一个“世界”的人,然后也很少找她说话,再然后就是用“嗯”“哦”来回复她的主动聊天,再然后联系越来越少,再然后连门都不敢出了,怕这个世界,有时虽然也会自嘲“活该孤独终老”,但是有啥办法呢?过年了,回到家,过着越来越淡的年,看着一同长大的人,吃着几十年一样的菜和饭,难不得矫情一下。

  • 相关阅读:
    「luogu2414」[NOI2011]阿狸的打字机
    【模板】KMP算法,AC自动机
    「luogu2336」[SCOI2012]喵星球上的点名
    「luogu2463」[SDOI2008]Sandy的卡片
    【模板】后缀数组
    「luogu1972」 [SDOI2009]HH的项链
    北师大部分题解
    D:Sequence Swapping
    Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 2)
    点双连通分量F. Simple Cycles Edges
  • 原文地址:https://www.cnblogs.com/w1570631036/p/5187101.html
Copyright © 2020-2023  润新知