日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python爬去学校_利用Python如何爬取自己学校的官网?用这招就行!

發(fā)布時間:2024/8/1 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python爬去学校_利用Python如何爬取自己学校的官网?用这招就行! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

查成績,算分?jǐn)?shù),每年的綜合測評都是個固定的過程,作為軟件開發(fā)者,這些過程當(dāng)然可以交給代碼去做,通過腳本進(jìn)行網(wǎng)絡(luò)請求獲取數(shù)據(jù),然后直接進(jìn)行計算得到基礎(chǔ)分直接填表就好了,查成績再手動計算既容易出錯也繁瑣,所以本篇的內(nèi)容就是開發(fā)一個爬蟲腳本取抓取成績表,至于綜合測評計算,這個沒什么意義這里就不說了,分?jǐn)?shù)都有了就都夠了。

我們的目的就是通過編寫腳本,模仿瀏覽器進(jìn)行請求獲取源碼,再進(jìn)行解析本地化(或者直接計算)

要抓取到數(shù)據(jù),其實方案不止一種,這里會介紹兩種不同的方案,達(dá)到同樣的目的:模仿瀏覽器進(jìn)行請求(速度快)

操作瀏覽器進(jìn)行請求(速度慢)

先說第一種,這種方案是普遍的爬蟲技術(shù),因為爬取的內(nèi)容不多,對速度要求也不夠,所以就是很簡單的一個爬蟲過程:

分析請求

模仿請求

對于普通的校園網(wǎng),一般不做流量限制,所以就算請求頻繁,也基本不用擔(dān)心IP被封禁,所以編寫爬蟲代碼可以不用太過擔(dān)心。先說我所在學(xué)校的校園網(wǎng),是杭州方正軟件公司開發(fā)的。

① 分析請求

分析請求很簡單,就是使用瀏覽器進(jìn)行請求,然后分析每個請求所發(fā)送和接收的信息,這里最簡單應(yīng)該是使用chrome的開發(fā)者模式(F12打開)

輸入用戶名和密碼,勾選已認(rèn)真閱讀,接著點擊登陸,這樣右邊的網(wǎng)絡(luò)窗口中會檢查到所有的網(wǎng)絡(luò)請求,我們只需要找到對應(yīng)登陸的一個(這里會帶有表單):

這個時候,我們可以通過一些測試工具,嘗試進(jìn)行請求對應(yīng)的這個地址,并且把表單提交上去試試登陸能否成功,如果成功的話,腳本也就可以模擬這個請求,這里用的是chrome商店的一個工具Postman,用法很簡單:

登陸成功之后,我們再進(jìn)行查詢成績:

這里可以看到這次得到了兩個新的請求(上圖紅框的前兩個)

仔細(xì)觀察會發(fā)現(xiàn),第一個請求頭中的Referer指向的是第二個請求的地址,所以可以知道,第二個請求是先于第一個請求發(fā)送的。其次,我們發(fā)現(xiàn)這個請求中也有表單。

再看第二個請求:

它的Referer指向第三個請求,而這個第三個請求實際上登陸成功之后,就已經(jīng)存在了,它就是請求到主界面的,而這個請求的類型是Get,所以也表明,第三個請求沒有傳遞任何信息給這個請求。

整理可以知道,流程是這樣的:

所以,我們先來模擬第二個,這個請求是Get類型,所以直接請求即可,但是會發(fā)現(xiàn)請求會失敗,原因是服務(wù)器不能知道我們已經(jīng)進(jìn)行登陸了:

所以最先想到的辦法是帶上第一個請求得到的Cookie,但是也是不行,這個時候要用到上面說的Referer標(biāo)識,這個標(biāo)識會告訴服務(wù)器請求來源,因為登陸成功會在服務(wù)器進(jìn)行登記,這個標(biāo)記會讓服務(wù)器知道請求來源于登陸成功的賬號:

此時請求返回正常,我們在源碼中可以發(fā)現(xiàn)有兩個隱藏的標(biāo)簽:

這兩個標(biāo)簽傳遞的,其實是第三個請求的參數(shù),這個時候,模擬第三個請求,并且添加對應(yīng)的Referer(第二個請求的URL),會發(fā)現(xiàn)請求也成功了:

這個請求中的url中的一個參數(shù)xm被我更改為1了,原本使用的是一種unicode加密編碼,把用戶名編碼過去了,但是實際上這個參數(shù)并沒有實際意義,%u的格式會破壞Python程序,所以這里直接改成1了。

② 模仿請求

請求分析完畢,就可以開始寫代碼了:

用到的包:

1 import requests, xlwt, os

2 from bs4 import BeautifulSoup

登錄:

1 def login(s, number, password):

2 print '正在登錄賬號:'+number

3 url = 'http://202.192.72.4/default_gdsf.aspx'

4 data = {'__EVENTTARGET': 'btnDL',

5 'TextBox1': number,

6 'TextBox2': password,

7 '__VIEWSTATE': '/wEPDwULLTExNzc4NDAyMTBkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQVjaGtZRIgvS19wi/UKxQv2qDEuCtWOjJdl',

8 'chkYD': 'on',

9 '__EVENTVALIDATION': '/wEWCgKFvrvOBQLs0bLrBgLs0fbZDAK/wuqQDgKAqenNDQLN7c0VAuaMg+INAveMotMNAuSStccFAvrX56AClqUwdU9ySl1Lo85TvdUwz0GrJgI='}

10 s.post(url, data)

11 return s.cookies

登錄操作沒有給后面的請求傳遞任何參數(shù),這里的Cookies不是必須的,但是登錄是必須的,這樣告訴服務(wù)器我們后面的請求才是合法的。

點擊查詢成績按鈕:

1 def get_data_for_grade(s, number, password):

2 url = 'http://202.192.72.4/xscj_gc.aspx?xh=' + number + '&xm=%B3%C2%D6%BE%B7%AB&gnmkdm=N121605'

3 referer = 'http://202.192.72.4/xs_main.aspx?xh=' + number

4 cookies = login(s, number, password)

5 response = s.get(url=url, headers={'Referer': referer}, allow_redirects=False, cookies=cookies)

6 source = response.text

7 soup = BeautifulSoup(source, 'html.parser')

8 view_state = soup.find('input', attrs={'id': '__VIEWSTATE'})['value']

9 event_validation = soup.find('input', attrs={'id': '__EVENTVALIDATION'})['value']

10 states = {'view_state': view_state, 'event_validation': event_validation, 'cookies': cookies, 'origin': url}

11 return states

第五行隊請求設(shè)置Referer,接著通過BeautifulSoup解析源碼得到兩個隱藏的標(biāo)簽里面value值,第三個請求要用到。

查詢所有成績請求:

1 def check_info(s, number, password):

2 url = 'http://202.192.72.4/xscj_gc.aspx?xh=' + number + '&xm=1&gnmkdm=N121605'

3 states = get_data_for_grade(s, number, password)

4 print '登錄成功,正在拉取成績'

5 data = {

6 '__VIEWSTATE': states['view_state'],

7 'ddlXN': '',

8 'ddlXQ': '',

9 'Button2': '',

10 '__EVENTVALIDATION': states['event_validation']

11 }

12 response = s.post(url, data=data, cookies=states['cookies'], headers={'Referer': states['origin']},

13 allow_redirects=False)

14 return response.text

得到成績單源碼之后,就可以進(jìn)行解析了,這里解析存放到xls表格中:

1 def writeToFile(source):

2 print '正在寫入文檔'

3 wb = xlwt.Workbook(encoding='utf-8', style_compression=0)

4 soup = BeautifulSoup(source, "html.parser")

5 span = soup.find('span', attrs={'id': 'Label5'})

6 sheet = wb.add_sheet('成績單', cell_overwrite_ok=True)

7 table = soup.find(attrs={'id': 'Datagrid1'})

8 lines = table.find_all('tr')

9 for i in range(len(lines)):

10 tds = lines[i].find_all('td')

11 for j in range(len(tds)):

12 sheet.write(i, j, tds[j].text)

13 try:

14 os.remove(span.text + '.xls')

15 except:

16 pass

17 wb.save(span.text + '.xls')

最后遍歷學(xué)號進(jìn)行爬取,這里只爬取默認(rèn)賬號密碼的成績:

1 for i in range(1, 55):

2 num = '2013034743001'

3 s = requests.session()

4 try:

5 if i <= 9:

6 writeToFile(check_info(s, num[:12] + str(i), num[:12] + str(i)))

7 else:

8 writeToFile(check_info(s, num[:11] + str(i), num[:11] + str(i)))

9 except:

10 pass

11 s.close()

第二種方案,是通過模擬瀏覽器來進(jìn)行登錄,點擊按鈕等操作獲取成績,這里用到的是自動化測試框架Selenium。

這種方案的優(yōu)點是我們不需要像第一種那樣要去分析請求,只需要告訴瀏覽器要怎么做就行了,但是缺點是速度慢。

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

2 from selenium import webdriver

3 from selenium.webdriver.common.by import By

4 from selenium.webdriver.support.wait import WebDriverWait

5 from selenium.webdriver.common.action_chains import ActionChains

6 from selenium.webdriver.support import expected_conditions as EC

7 from selenium.common.exceptions import NoSuchElementException

8 from selenium.common.exceptions import NoAlertPresentException

9 from bs4 import BeautifulSoup

10 import xlwt

11 import os

12

13

14 class Script():

15 def setUp(self):

16 self.driver = webdriver.Chrome()

17 self.driver.implicitly_wait(10)

18 # self.driver.maximize_window()

19 self.base_url = "http://202.192.72.4/"

20 self.verificationErrors = []

21 self.accept_next_alert = True

22

23 def test_jb(self, num):

24 driver = self.driver

25 driver.get(self.base_url + "/default_gdsf.aspx")

26 driver.find_element_by_id("TextBox1").clear()

27 driver.find_element_by_id("TextBox1").send_keys(num)

28 driver.find_element_by_id("TextBox2").clear()

29 driver.find_element_by_id("TextBox2").send_keys(num)

30 driver.find_element_by_id("chkYD").click()

31 driver.find_element_by_id("btnDL").click()

32 WebDriverWait(driver, 5).until(EC.alert_is_present()).accept()

33 self.open_and_click_menu(driver)

34 retry = 0

35 while retry <= 2:

36 try:

37 driver.switch_to.frame(driver.find_element_by_id('iframeautoheight'))

38 WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, "//input[@id='Button2']")))

39 break

40 except:

41 print '重新點擊按鈕'

42 driver.switch_to.parent_frame()

43 self.open_and_click_menu(driver)

44 retry += 1

45 else:

46 print '重試失敗'

47

48 source = driver.page_source

49 driver.find_element_by_xpath("//input[@id='Button2']").click()

50

51 def source_change(driver):

52 if source == driver.page_source:

53 return False

54 else:

55 return driver.page_source

56

57 self.writeToFile(WebDriverWait(driver, 10).until(source_change))

58 driver.quit()

59

60 def open_and_click_menu(self, driver):

61 menu1 = WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, "//ul[@class='nav']/li[5]")))

62 menu2 = driver.find_element_by_xpath("//ul[@class='nav']/li[5]/ul/li[3]")

63 ActionChains(driver).move_to_element(menu1).move_to_element(menu2).click(menu2).perform()

64

65 def is_element_present(self, how, what):

66 try:

67 self.driver.find_element(by=how, value=what)

68 except NoSuchElementException as e:

69 return False

70 return True

71

72 def is_alert_present(self):

73 try:

74 self.driver.switch_to_alert()

75 except NoAlertPresentException as e:

76 return False

77 return True

78

79 def close_alert_and_get_its_text(self):

80 try:

81 alert = self.driver.switch_to_alert()

82 alert_text = alert.text

83 if self.accept_next_alert:

84 alert.accept()

85 else:

86 alert.dismiss()

87 return alert_text

88 finally:

89 self.accept_next_alert = True

90

91 def tearDown(self):

92 self.driver.quit()

93 self.assertEqual([], self.verificationErrors)

94

95 @staticmethod

96 def writeToFile(source):

97 wb = xlwt.Workbook(encoding='utf-8', style_compression=0)

98 soup = BeautifulSoup(source, "html.parser")

99 span = soup.find('span', attrs={'id': 'Label5'})

100 sheet = wb.add_sheet('成績單', cell_overwrite_ok=True)

101 table = soup.find(attrs={'id': 'Datagrid1'})

102 lines = table.find_all('tr')

103 for i in range(len(lines)):

104 tds = lines[i].find_all('td')

105 for j in range(len(tds)):

106 sheet.write(i, j, tds[j].text)

107 try:

108 os.remove(span.text + '.xls')

109 except:

110 pass

111 wb.save(span.text + '.xls')

112

113

114 if __name__ == "__main__":

115 # unittest.main()

116 s = Script()

117

118 for i in range(1, 50):

119 num = '2013034743101'

120 s.setUp()

121 try:

122 if i <= 9:

123 s.test_jb(num[:12] + str(i))

124 else:

125 s.test_jb(num[:11] + str(i))

126 except:

127 pass

這種方法的意義只是熟悉一下自動化測試框架,因為速度實在太慢了,也就不詳細(xì)介紹了,這里粗略說一下,其實原理就是通過查到網(wǎng)頁中對應(yīng)的控件,進(jìn)行點擊或者懸浮于上面等等的操作,一步一步的到達(dá)最后的成績單,要做的是控制整個流程,明確在什么時候應(yīng)該停一下等控件出現(xiàn),什么時候要去點擊。

而且到目前為止,這個框架還是有一些Bug的,比如火狐瀏覽器的驅(qū)動無法實現(xiàn)在一個按鈕上Hover的操作等等。

總結(jié)

以上是生活随笔為你收集整理的python爬去学校_利用Python如何爬取自己学校的官网?用这招就行!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。