大概兩個禮拜前我們已經有用 requests
+ BeautifulSoup
兩個套件來把文章爬取下來了,今天會把相關的邏輯都移植到 Scrapy 框架中。先附上完整程式碼,接著會有相關的說明。
Scrapy 也支援 CSS 和 XPath 選擇器,分別對應回應實例的 css(query) 方法和 xpath(query) 方法。
如果要取得純文字或屬性內容,對應的選擇器如下:
說明 | CSS | XPath |
---|---|---|
純文字 | .css('::text') | .xpath('text()') |
屬性 | .css('::attr(attr-name)') | .xpath('@attr-name') |
7 行,因為 iT 邦幫忙的網域 ithelp.ithome.com.tw
是子網域,所以這邊改成允許 ithome.com.tw
就可以了。
allowed_domains = ['ithome.com.tw']
9~11 行,因為我們是以網址帶參數的方式換頁,這邊就不使用 start_urls
這個屬性,改成覆寫 start_requests()
方法,用每一頁的網址來發送請求,並指定使用 parse(response)
方法來處理回應。
昨天有講到
start_requests()
和parse(response)
方法都必須回傳可迭代的(iterable)請求或爬取到的項目實例,所以都是用 yield 來回傳。
def start_requests(self):
for page in range(1, 11):
yield scrapy.Request(url=f'https://ithelp.ithome.com.tw/articles?tab=tech&page={page}', callback=self.parse)
13~24 行,處理列表頁回應的方法,邏輯跟之前一樣。比較特別的是在 24 行用了 response.follow()
方法來取得文章的請求,同時指定使用 parse_article(response)
發訪來處理文章的回應。
Scrapy 提供了 response.urljoin(url) 和 response.follow(url) 兩個方法來方便處理相對路徑,前者只會回傳一個對應的絕對路徑,後者則會回傳使用對應絕對路徑的請求。
yield response.follow(article_url, callback=self.parse_article)
26~65 行,處理文章回應的方法,邏輯也是跟之前幾乎相同就不多做說明了。注意在 65 行我們一樣用 yield
回傳爬取到的項目。
爬蟲名稱是 ithome
,所以可以直接執行 scrapy crawl ithome
來啟動爬蟲。
可以在 console 中看到我們抓到的文章,如果要將結果儲存成 JSON 檔案,可以在執行時多加一個參數 scrapy crawl ithome -o ithome.json
或 scrapy crawl ithome -o ithome.csv
,就可以在專案目錄中看到我們爬取到的結果存成 ithome.json
檔案了。