2015年5月30日 星期六

[Python][教學] 網路爬蟲(crawler)進階實務-- 自動爬蟲(一)

圖片來源:http://www.richbank.com.tw/CashierAndRegistration.html

前面幾篇[Python][教學] 網路爬蟲(crawler)實務(上)–網頁元件解析[Python][教學] 網路爬蟲(crawler)實務(下)–爬蟲策略以及設定介紹了撰寫爬蟲程式基本的觀察以及實作方式.這樣的方式爬一兩個小網站還可以,但是如果要爬比較複雜或是多個網站就比較難維護.因此實務上比較常使用Scrapy這個爬蟲框架來處理,這次將介紹更進階的使用方法給各位.


Scrapy基本設定可參考[Python][教學] Scrapy(Web Crawler) to PostgreSQL(一)簡介 & 網路爬蟲基本設定).本篇將直接介紹核心的爬蟲邏輯.
這次作為範例的是某醫院的掛號網站,目標則是一次抓取所有科別的掛號資料(因為網站觀看人數不少,怕大家都照著code來做造成對方網站困擾,所以不公佈名字,請見諒orz),不過網站架構大致如下:
  • 掛號首頁
    • XX1科
      • 醫生A資料
      • 醫生B資料
    • XX2科
      • 醫生C資料
    • XX3科
    • …etc
      如果我們要每個科別都寫爬蟲的話,那只會累死自己,所以我們選擇使用更進階的爬蟲來幫我們處理這樣不一樣,卻又某些地方相似的網站結構.
先來看第一部分spyder/crawler.py
# -*- coding: utf-8 -*-
import sys
import scrapy
from datetime import datetime
from scrapy.http import Request, FormRequest, TextResponse
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy import log
from ..items import HosItem
#from scrapy.stats import Stats

class Crawler(CrawlSpider):
    name = "crawler"
    allowed_domains = ["gov.tw"]
    start_urls = [
        "https://ip/webadministration/ClinicTable.aspx"
    ]

    rules = [
        Rule(LinkExtractor(allow = ('\?Dept=\w+.*')),
        callback = 'parse_table', follow = True),

        Rule(LinkExtractor(allow = ('\?Dept=\w+.*week=2')),
        callback = 'parse_table', follow = True)
     ]
開頭先把需要用的套件import進來,接著起一個Crawler的物件,繼承自CrawlerSpider.Scrapy預設的爬蟲是BaseSpider,也是最基本的爬蟲功能,所有要用的功能都要自己一步一步慢慢寫.CrawlerSpider可以自動根據特定的規則搜尋網頁官方文件
當繼承CrawlerSpider物件後,一樣先在start_urls設定起始的位址(抱歉這邊還是得隱碼),接著就可以在rules的地方設定要自動搜尋的規則.
rules裡面可以設定複數以及階層式的規則,原理就是從start_url進去後,搜尋符合規則的連結位址.例如第一個Rule
Rule(LinkExtractor(allow = ('\?Dept=\w+.*')),callback = 'parse_table', follow = True)
LinkExtractor是用來比對網址和決定套用方法的物件,官方說明上用的是SgmlLinkExtractor,但是實測後遇到中文網址會有問題,所以建議就使用LinkExtractor.裡面幾個參數分別代表:
  • allow= 後面接遵循的規則,栗子為為符合\?Dept=w+.*的任何連結,\?w+皆為正規表達式,可以模糊比對網址條件.
  • callback= 接處理比對到網址的function,會使用在這個function中的parser來處理找到的網址.
  • follow= 如果為True,代表繼續從目標網址中抓符合規則的網址出來處理.
下回我們將介紹更多奇怪的parser方式,當網頁不是那麼好處理的時候該怎麼辦?
更多code可以參考https://github.com/bryanyang0528/HospitalCrawler