路漫漫其修遠兮,吾將上下而求索

0%

爬蟲實戰 - Using Python3 Part3

Level2: 處理分頁

這次的目標網頁多了分頁的功能,因此我們的requests 就必須依據分頁的數量去存取,步驟如下:

  1. 設定n = 1
  2. 檢查第n頁有無資料,若有則下載網頁並轉換成DOM 格式,若無則輸出結果
  3. 解析、處理網頁內容
  4. 設定n = n+1,並回到第2步驟

由於import 的套件都一樣,所以只要修改main function即可。

1
2
3
4
5
6
7
8
9
# -*- coding: utf8 -*-
from lxml import etree
import requests

def main():
pass

if __name__ == "__main__":
main()

首先我們需要設定一個無窮迴圈,考慮現實情況下我們不一定知道目標網站共有幾頁的資料,不然也可以直接設定12圈來完成這題的目標:

1
2
while Ture:
pass

無窮迴圈的話一定要給一個終止條件,所以我們先給一個很大的頁數並觀察沒有資料的網頁結構長怎樣

從網頁原始碼的結果得知,沒有資料的話網頁的 <table> 只有表頭而已,因此改良後的判斷條件如下:

1
2
3
4
5
6
7
8
9
10
page = 1
while True:
result = requests.get("http://axe-level-1.herokuapp.com/lv2?page=%s" % str(page))
result.encoding = 'utf8'
root = etree.fromstring(result.text, etree.HTMLParser())
rows = root.xpath("//table[@class='table']/tr[position()>1]")
if len(rows) == 0:
break
else:
page+=1

由於有很多頁數, 所以 request 的目標必須是動態的字串,透過 rows 變數可以知道目前的資料列共有幾行,如果該頁沒有資料列的話表示已經到最後一頁了所以離開迴圈,若還沒到最後一頁我們就可以統計目前這頁的所有資料。

統計方法跟Level 1其實差不多,取得 <tr> 下的每個 <td>,再把其結果分別儲存起來

1
2
3
for row in rows:
column = row.xpath("./td/text()")
tmp = '{"town": "%s", "village": "%s", "name": "%s"},' % (column[0], column[1], column[2])

最後完整的Code 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding: utf8 -*-
from lxml import etree
import requests

def main():
page = 1
jsonData = '['
while True:
result = requests.get("http://axe-level-1.herokuapp.com/lv2?page=%s" % str(page))
result.encoding = 'utf8'
root = etree.fromstring(result.text, etree.HTMLParser())
rows = root.xpath("//table[@class='table']/tr[position()>1]")
if len(rows) == 0:
break
else:
tmp = ""
for row in rows:
column = row.xpath("./td/text()")
tmp += '{"town": "%s", "village": "%s", "name": "%s"},' % (column[0], column[1], column[2])
jsonData += tmp
page+=1
# 刪除最後一個逗號
print(jsonData[0:-1] + "]")

if __name__ == "__main__":
main()

這一章節就介紹到這邊結束,下一章節會介紹當網站有使用到SESSION 以及阻擋機器人情況下的爬蟲。