date: 2017-03-14 21:08:42

Holi需要。
之前爬的課表,現(xiàn)在需要將那些個一連串的字符串分割成想要的單獨的數(shù)據(jù),做個性化推送。
程序的前面和之前一樣,模擬登錄。
在處理選課/改課這個網(wǎng)頁的時候,還是蠻復(fù)雜的。
遇神殺神,見鬼殺鬼。
爬蟲
def Store(self):
# 改課選課
grade_page = self.session.get(
"http://yjsxt.xidian.edu.cn/electiveForwardAction.do")
bsObj = BeautifulSoup(grade_page.text, "html.parser")
table = bsObj.findAll("table", {"class": "list_2title"})[0]
rows = table.findAll("tr")
# 刪除特定的標(biāo)簽和其標(biāo)簽下的內(nèi)容
# 方法:
# 去除標(biāo)簽:[s.extract() for s in soup('script')]
[s.extract() for s in bsObj.findAll(
'td', attrs={'class': "special_background textLeft"})]
csvFile = open('./xuankegaike.csv', 'w', newline='', encoding='utf-8')
writer = csv.writer(csvFile)
writer.writerow(('課程編號', '課程名稱', '學(xué)分', '學(xué)位課', '上課學(xué)期',
'任課教師', '校區(qū)', '上課地點/星期/節(jié)次/周次', '分班號'))
csvRow = []
try:
for row in rows:
csvRow = []
# for cell in row.findAll('td')[:-1]:
for cell in row.findAll('td', attrs={'valign': "middle"})[:-1]:
csvRow.append(cell.get_text().strip().replace(' ', ''))
writer.writerow(csvRow)
finally:
csvFile.close()
csvFile1 = open('./xuankegaike.csv', 'r', encoding='utf-8')
reader = csv.DictReader(csvFile1)
正個頁面有一張大table,但是里面分布的真不整齊。
新方法s.extract():
刪除特定的標(biāo)簽和其標(biāo)簽下的內(nèi)容
方法:
去除標(biāo)簽:[s.extract() for s in soup('script')]
s.extract()方法可以刪除標(biāo)簽或指定標(biāo)簽下的內(nèi)容。
獲取指定td下的內(nèi)容:
row.findAll('td', attrs={'valign': "middle"})[:-1]:
這幾次爬蟲對于切片還是用的很好的。
爬回待處理table:
課程編號,課程名稱,學(xué)分,學(xué)位課,上課學(xué)期,任課教師,校區(qū),上課地點/星期/節(jié)次/周次,分班號
G00FL1020,綜合英語,2,是,2016秋,培養(yǎng)辦,北校區(qū),,免修班
G00HA1012,科學(xué)道德與學(xué)風(fēng),0,是,2016秋,梁昌洪,南校區(qū),,不分班
G00HA1010,中國特色社會主義理論與實踐,2,是,2016秋,肖群,北校區(qū),"J-201/星期一/(9-11)2,3,4,5,7,8,9,10,11,12,13",02
G00HA1011,自然辯證法概論,1,是,2017春,朱丹瓊,北校區(qū),"J-205/星期一/(3-4)2,3,4,5,7,8,9,11,12",07
G00FL1023,英語聽說,1,是,2016秋,姜寧,北校區(qū),"西-508/星期二/(7-8)2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18",07
G00FL1026,英美文化,1,是,2017春,鄒甜甜,北校區(qū),"西-514/星期一/(1-2)2,3,4,5,7,8,9,11,12,13,15,16,17,18",01
Z00MS1031,工程優(yōu)化方法及應(yīng)用,3,是,2016秋,寇曉麗,北校區(qū),"J-205/星期四/(9-11)2,4,5,7,8,9,10,11,13,14,15,16,17,18,19",01
Z08EE1011,算法設(shè)計技術(shù)與方法,3,是,2016秋,公茂果,北校區(qū),"J-304/星期三/(9-11)18J-304/星期五/(9-11)2,5,7,8,9,10,11,12,13,14,15,16,17,18,20",不分班
Z08TE1107,寬帶無線通信,3,是,2016秋,盛敏,北校區(qū),"J-204/星期一/(3-4)2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18J-204/星期四/(1-2)2,4,8,10,12,14,16,18",不分班
Z08TE1140,信號檢測與估值理論,3,是,2017春,李穎,北校區(qū),"J-208/星期三/(3-4)2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17J-208/星期五/(1-2)2,4,6,8,10,12,14,16",不分班
G00HA0040,體育,0.5,否,2016秋,白光斌,北校區(qū),"體育館/星期三/(3-4)3,4,5,7,8,9,10,11,12,13",01
G00HA0041,體育,0.5,否,2017春,白光斌,北校區(qū),"體育館/星期三/(5-6)2,3,4,5,6,7,8,9,10,11",02
Z08TE1222,擴頻通信系統(tǒng),2,否,2016秋,劉乃安,北校區(qū),"J-205/星期二/(9-11)4,5,7,8,9,10,11,12,13,14,15",不分班
G00HA1016,知識產(chǎn)權(quán)與專利申請,1,否,2016秋,王喜媛,北校區(qū),"J-101/星期二/(1-2)3,4,5,7,8,9,10,11,12",01
G00GS1001,企業(yè)實習(xí)報告,2,否,2016秋,培養(yǎng)辦,北校區(qū),,不分班
G00GS1002,開題報告,2,否,2016秋,培養(yǎng)辦,北校區(qū),,不分班
G00GS1003,中期檢查,2,否,2016秋,培養(yǎng)辦,北校區(qū),,不分班
Z08TE1212,MIMO系統(tǒng)與OFDM傳輸技術(shù),2,否,2016秋,趙力強,北校區(qū),"J-204/星期二/(5-6)3,4,5,7,8,9,10,11,12J-204/星期四/(5-6)4,5,7,8,9,10,11",不分班
Z08TE1216,圖像工程,3,否,2016秋,盧朝陽,李靜,北校區(qū),"J-208/星期五/(5-8)2,4,5,7,8,9,10,11,12,13,14,15",不分班
Z08EE1238,科學(xué)精神與方法專題講座,2,否,2017春,梁昌洪,北校區(qū),"圖書館報告廳(3樓)/星期四/(9-11)3,4,5,6,7,8,9,10,11,12,13",不分班
前幾項都是可以直接存到MySQL,現(xiàn)在要做的就是把 上課地點/星期/節(jié)次/周次 這一欄切割后存進MySQL。
方法:split()
首先分析爬回的table。
里面的上課地點/星期/節(jié)次/周次可以分為三類:
- 空。比如綜合英語,科學(xué)道德與學(xué)分。
- 一周只有一節(jié)課的課。
- 一周有兩節(jié)課的課。
講道理是要按照三種方法來對字符型切割。
但是該怎么來分類。
我的第一個思路是用:try,except。
但是這幾個并不是用來處理選擇結(jié)構(gòu)的吧。
但是try,except,else,finally還是很好用的。
選擇結(jié)構(gòu)?難道不應(yīng)該是if,else嗎?
對!就是它!
對這幾種不同類型的上課地點/星期/節(jié)次/周次字符串的長度進行分析,三類的長度大概如下:
第一類:長度為0;
第二類:長度為50~60;
第三類:長度60~90.
這樣一來就按照上課地點/星期/節(jié)次/周次的長度來判斷分割方法。
# # 使用 execute() 方法執(zhí)行 SQL 查詢
try:
if len(e['上課地點/星期/節(jié)次/周次']) > 60:
cursor.execute(sql, (
e['課程編號'].strip(),
e['課程名稱'].strip(),
e['學(xué)分'].strip(),
e['學(xué)位課'].strip(),
e['上課學(xué)期'].strip(),
e['任課教師'].strip(),
e['校區(qū)'].strip(),
e['上課地點/星期/節(jié)次/周次'].split("/")[0],
e['上課地點/星期/節(jié)次/周次'].split("/")[1],
e['上課地點/星期/節(jié)次/周次'].split(
"(")[1].split(")")[0][0],
e['上課地點/星期/節(jié)次/周次'].split("/")[2][5:-
5].lstrip(')'),
e['分班號'].strip()))
# 存兩次
cursor.execute(sql, (
e['課程編號'].strip(),
e['課程名稱'].strip(),
e['學(xué)分'].strip(),
e['學(xué)位課'].strip(),
e['上課學(xué)期'].strip(),
e['任課教師'].strip(),
e['校區(qū)'].strip(),
e['上課地點/星期/節(jié)次/周次'].split("/")[2][-5:],
e['上課地點/星期/節(jié)次/周次'].split("/")[3],
e['上課地點/星期/節(jié)次/周次'].split("/")[4][1],
e['上課地點/星期/節(jié)次/周次'].split(
"/")[4][5:].lstrip(')'),
e['分班號'].strip()))
else:
cursor.execute(sql, (
e['課程編號'].strip(),
e['課程名稱'].strip(),
e['學(xué)分'].strip(),
e['學(xué)位課'].strip(),
e['上課學(xué)期'].strip(),
e['任課教師'].strip(),
e['校區(qū)'].strip(),
e['上課地點/星期/節(jié)次/周次'].split("/")[0],
e['上課地點/星期/節(jié)次/周次'].split("/")[1],
e['上課地點/星期/節(jié)次/周次'].split(
"(")[1].split(")")[0][0],
e['上課地點/星期/節(jié)次/周次'].split(
"/")[2][5:].lstrip(')'),
e['分班號'].strip()))
except:
# else len(e['上課地點/星期/節(jié)次/周次']) == 0:
cursor.execute(sql, (
e['課程編號'].strip(),
e['課程名稱'].strip(),
e['學(xué)分'].strip(),
e['學(xué)位課'].strip(),
e['上課學(xué)期'].strip(),
e['任課教師'].strip(),
e['校區(qū)'].strip(),
e['上課地點/星期/節(jié)次/周次'],
e['上課地點/星期/節(jié)次/周次'],
e['上課地點/星期/節(jié)次/周次'],
e['上課地點/星期/節(jié)次/周次'],
e['分班號'].strip()))
if
下面包含兩部分:
- 字符串長度大于60的,即一周有兩節(jié)課的情況。
- 一周有兩節(jié)課的情況,將該課程在數(shù)據(jù)庫存兩次,但是兩次的上課時間、地點、周次是不一樣的。
else
處理長度小于60的,即一周只要一節(jié)課的課。
except
當(dāng)前兩項都出現(xiàn)異常時,其必然是第一類情況,字符串為空,直接存進就可以。
split
split的幾種用法:
split("/")[0]:按照“/”分割,取第一個切片。
split("(")[1].split(")")[0][0]
取“()”內(nèi)的字符串的第一個。
最后
將里面的簡單字符串都處理為數(shù)字。
for e in reader:
# 是否是學(xué)位課
if e['學(xué)位課'] == '是':
e['學(xué)位課'] = '1'
else:
e['學(xué)位課'] = '0'
# 學(xué)期
if e['上課學(xué)期'] == '2016秋':
e['上課學(xué)期'] = '0'
else:
e['上課學(xué)期'] = '1'
存進數(shù)據(jù)庫了。

這次還是發(fā)現(xiàn)了很多的問題。
歸根結(jié)底,還是基礎(chǔ)不太好,是得花時間在研習(xí)下Python基礎(chǔ)。