【爬蟲】(八)Python之爬蟲和數(shù)據(jù)小解析

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é)次/周次可以分為三類:

  1. 空。比如綜合英語,科學(xué)道德與學(xué)分。
  2. 一周只有一節(jié)課的課。
  3. 一周有兩節(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

下面包含兩部分:

  1. 字符串長度大于60的,即一周有兩節(jié)課的情況。
  2. 一周有兩節(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ǔ)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容