Skip to content

Latest commit

 

History

History
164 lines (146 loc) · 5.73 KB

課程爬蟲.md

File metadata and controls

164 lines (146 loc) · 5.73 KB

Scrapy課程爬蟲教學

請先參考前一篇的scrapy教學

安裝環境

pip install scrapy requests simplejson pyprind selenium bs4

流程

  1. 爬查詢系統首頁,得到系所和年級的清單
  2. 分析該學校是用何種方式送請求,通常都是把系所代號等等放在querystringget方式傳出去;另外一種就是用post系所代號送出去
  3. 把所有系所的request都送一遍然後爬回來
  4. 透過Scrapyitem自動形成團隊要的Schema

中科大的scrapy示範

完整程式碼在此,請大家搭配服用:超連結

  1. 建立該學校的spiders:

    1. scrapy genspider 學校名稱(NUTC) 網域(aisap.nutc.edu.tw)
  2. 編輯spiders/NUTC.py,import團隊定義好的item

    from UCrawler.items import UcrawlerItem
    

    欄位的意義:

    department 開課系所
    for_dept 給哪個系所上的課
    grade 年級
    title 課程名稱
    time 時間
    credits 學分
    obligatory_tf 必修或選修
    professor 教授
    location 地點
    code 課程代碼
    note 備註
    campus 校區
    
    1. class variable部份:

      1. start_urls填入課程查詢的網址: start_urls = ['https://aisap.nutc.edu.tw/public/day/course_list.aspx']
      2. class variable可以放一些翻譯對對照table,例如中文的星期轉成數字:
      day_table = {
            '一':1,
            '二':2,
            '三':3,
            '四':4,
            '五':5,
            '六':6,
            '日':7,
        }
      

      建立一份課程類別的清單。api會以此清單做課程的分類
      類別固定這三種:通識類, 體育類, 其他類
      此變數定義在spider的class variable裏面
      參考中科大的scrapy範例

      genra = {
          '通識':'通識類',
          '體育類':'體育類',
          '語言':'其他類',
          'xxxx':'通識類',
          'yyyy':'體育類',
          'zzzz師培':'其他類',
          'zzzz軍訓':'其他類',
          ...
      }
      
    2. start_requests部份: start_requests的角色是回傳所有scrapy將要去拜訪的網址
      在爬課程網站時,所有將拜訪的網址
      就是所有系所的組合

      start_requests統一建立一個 dept_table
      裏面包含系所名稱和系所代碼的對照表
      每間學校對於不同年級可能有不同的系所代碼
      以下用中科中山做示範

      {
        "企管一乙": "1120170202",
        "企管一甲": "1120170201",
        "企管一1": "1420170191",
        "企管三乙": "1120150202",
      }
      or
      {
        "中學學程": "AB0A",
        "中文系": "B101",
        "企管系": "B401",
        "光電系": "B309",
        "劇藝系": "B106",
        "化學系": "B202",
        "國語文": "AC1C",
        "外文系": "B102",
        "工學院": "B30A",
        ...
      }
      

      以及 latest_semester變數,用來存放最新的學年字串
      ex:1061

      再來就是骨幹的for loop
      使用前面定義好的dept_table以及latest_semester去依序拜訪
      每個request都傳到self.parse去做進一步處理

      for code in pyprind.prog_bar(dept_table.values()):
              yield scrapy.Request('https://aisap.nutc.edu.tw/public/day/course_list.aspx?sem={}&clsno={}'.format(latest_semester, code), self.parse)
      
    3. parse部份: 大部分的查詢結果如下: 課程查詢結果
      都會有多門課程在同一個網頁
      所以必須要用for loop
      把每一行(也就是每一門課程)
      弄成一個item物件再yield
      實作上分成3個步驟:

      1. schema:每間學校他們table的欄位都不一樣
        請先用soup選取,並且取名成schema
      2. dataList:將每一門課程,都用dict(zip(schema, 課程))的方式,整理成一個像這樣的陣列:
        [
          {
            'campus': 'NSYSU',
            'code': 'CM498',
            'credits': 3.0,
            'department': '管理學院',
            'for_dept': '管理學院',
            'grade': '0',
            'location': '管CM 4112',
            'note': '《講授類》\xa0※英語授課',
            'obligatory_tf': False,
            'professor': '張姮燕',
            'time': [{'day': 1, 'time': ['6', '7', '8']}],
            'title': '跨文化管理CROSS-CULTURE MANAGEMENT'
          },
          ...
          ...
          ...
        ]
        
      3. 用一個for loop,迭代dataList,把每個dict轉成item物件然後yield
        for data in dataList:
            courseItem = UcrawlerItem()
            courseItem['code'] = data['課程代碼']
            courseItem['note'] = data['組別']
            courseItem['campus'] = 'NUTC'
        
            # 省略多個item欄位
            ...
        
            yield courseItem
        
  3. 執行:scrapy crawl NUTC -o NUTC.json -t json就能夠得到中科的課程爬蟲了,其他學校如法炮製。

  4. 完整程式碼:超連結