---
tags: System Architecture
---
Internet Protocol
===
# TCP/IP 網路協議
* [jupyter notebook 架構分析](https://blog.just4fun.site/jupyter-notebook-architecture.html)
本篇是基於以下這本好書為開始,將自己所看的網路相關知識做簡單紀錄:
![](https://i.imgur.com/b887Zs3.jpg)
<br>
## 為什麼想看這本書:
1. 現今IT發展已經脫離不了網路通訊,包含各種數據處理也是需要透過網路進行各種活動,而TCP/IP毫無疑問是現今最普遍的標準協定。
2. 處理資料的軟體工具(Kafka、Elastic Search、all kind of Data Base....等),大多是基於TCP/IP傳輸層上另外設計應用層的協定,雖然不了解網路協定還是可以使用這些工具,但了解網路協議有助於更深入了解這些工具,例如:
* 案例1.Docker 的 Bridge 模式網路會在主機建立一組docker0的虛擬網橋(software bridge),其作用和實體交換機類似,這樣可以讓主機上相同bridge的不同容器連線溝通,而且 docker bridge driver 會自動在 Host 上設定相對應的 rule(iptables, network namespace),讓 container 的網路可以正確的被使用,而更下層機制是藉由在主機上建立一對虛擬網卡veth pair裝置,Docker將veth pair裝置的一端放在新建立的容器中,並命名為eth0(容器的網絡卡),另一端放在主機中,以vethxxx這樣類似的名字命名,並將這個網路裝置加入到docker0網橋中來實現,有這些認知,在部屬多容器上可以更深入的理解。
[Docker Bridge Network 簡介](https://godleon.github.io/blog/Docker/docker-network-bridge/)
![](https://i.imgur.com/4n6RL3e.jpg)
* 案例2.Kafka就是基於TCP上另外建立應用層的通訊協定,以便達到"multiplex requests, the ability to simultaneously poll many connections"...等目的。
[The Explanation Behind The Protocols That Kafka Is Using](https://streamdata.io/blog/explanation-behind-protocols-that-kafka-is-using/)
* 案例3
* [Top 15 Standard IoT Protocols That You Must Know About](https://www.ubuntupit.com/top-15-standard-iot-protocols-that-you-must-know-about/)
## OSI 7 層模型
### 前導-網路協定(protocol)
* 協定:
* 比喻方式來說,協定就是共同的約定,就像語言一樣,英文可以算是是一種協定,在這協定下不同母語可以透過語言來通訊。
* 本質上來說,電腦間可以透過網際網路實現通訊,就是依靠大家都認同的機制來達成,這些機制統稱為協定,其必須在定義的『作用』下約定共同『規格』,『規格』內容就包含通訊方法,例如對講機的通訊可以視為是一種協定,其必須在約定的頻率和實體裝置下才能進行溝通。
* 補充-網際網路:
* 網際網路(Internet):我們所知的網際網路已經變成是一個專有名詞,表示為透過**協定**連接全世界裝置的龐大網絡,很多人會將其和 WWW 劃上等號,但是他們是不同的事情。
* 網路的應用:我們所熟悉的 WWW、HTTP、FTP、E-mail...等都是建立在網際網路上較頂層的應用,其下是靠各種層面**基礎協定**來支撐,而目前最廣泛應用通訊協定就是TCP/IP。
### 協定理想標準與層級化:
* 一個完整的通訊,涉及了各種複雜的過程,很自然的,協定可以因應作用的不同而分出不同層次以簡化問題,通訊兩方同層次會盡量作到可以獨立變動而不影響其他層的運作,但以整體通訊角度來看,上層的功能需要以下層功能為基礎才能達到網路通訊目的。
* 以電話來比喻的話,電話設備互相連結機制是一種基礎的協定;聲音傳遞機制是層次較高的協定;而溝通用的語言(中文)又是更高層次的溝通協定,語言層次可以隨意更換(中文換英文)而不影響下層電話本身的通訊,反之改用對講機的話也不影響語言的選定,上層語言溝通必須靠下層電話網絡基礎才能實現。
* 網路通訊比電話複雜許多,因此想藉由分層來將功能分割,讓網路協定變的更簡單且具獨立性,而理想上理論模型就是**OSI的7層**架構,在分層架構下,下層級會接收特定服務,再為上層級提供特定服務,而各層之間的溝通約定就是協定,雖然其層次分的太細,實務上實現有點難度,但是是值得了解的一個架構。
* ***協定分層概念***
![分層概念](https://i.imgur.com/fie2F6w.jpg)
### OSI 7 層模型各層簡介
* 下圖簡單介紹OSI的7層模型:
![](https://i.imgur.com/44q32Iq.jpg)
1. 實體層(Physical Layer):
* 電腦的位元串(0/1)與實際物理線路上的高低電壓(或燈光閃爍)...等傳遞連結的協定
* 主要媒介是網路卡及網路線...等,而每個網路卡都有實體位址MAC。
2. 資料連結層(Data Link Layer):
* 在實體層直接連接的節點間(ex:乙太網路直接連線的電腦),適用資料連結層。
* 資料連結層將實體層的數位訊號封裝成一組符合邏輯傳輸資料,這組訊號稱為資料訊框(Data Frame),訊框內包含媒體存取控制(Media Access Control,MAC)位址。
* 訊框就是真實資料前段約定好格式的表頭資料, 可以想像程對講機講話時要先調好的頻率,或是古代祕密通訊要先有暗號一樣
* 其實各層的協定都有各自約定好的表頭格式(自己層的暗號)
* 不少網路協定是在資料連結層上運作,我們較常聽到的是非同步傳輸模式(Asynchronous Transfer Mode,ATM),以及點對點協定(Point-to-Point Protocol,PPP),網路交換器(Switch)是這個層級常見的設備,主要在區域網路上運作,先前 Docker bridge 的交換器類似本設備的軟體實現。
3. 網路層(Network Layer):
* 網路層定義**網路路由**及定址功能將多個網路連結起來,以便讓通訊端點共同執行封包處理作業,是不直接實體連接端點可以通訊的重要協定
* 在TCP/IP中,本層最重要的協定就是網際網路協定(Internet Protocol,IP)
* 資料在傳輸時,該協定將IP位址加入傳輸資料內,並把資料組成封包(Packet),在網路上傳輸時,封包裡面的IP位址會告訴網路設備這筆資料的來源及目的地
* 我們常用的網址,本質上就是 IP 的另一種表現方式
* 路由器及 Layer3 交換器即屬於第三層的網路設備,主要以IP作為資料傳輸依據,它們大多在企業機房內運作。
4. 傳輸層(Transport Layer):
* IP 找到端點電腦後,透過傳輸層在兩台主機間創造邏輯性的通訊,白話一點就是找到對方主機後,怎麼讓應用程式溝通(Ex: E-mail, HTTP, FTP...)
* 在TCP/IP中,傳輸層透過連接埠編號(port)辨別應用程式,
* 傳輸層還負責電腦整體的資料傳輸及控制,是OSI模型中的關鍵角色,它可以將一個較大的資料切割成多個適合傳輸的資料,替模型頂端的第五、六、七等三個通訊層提供流量管制及錯誤控制。
* 傳輸控制協定(Transmission Control Protocol,TCP)是我們常接觸具有傳輸層功能的協定,它在傳輸資料內加入驗證碼,當對方收到後,就會依這個驗證碼,回傳對應的確認訊息(ACK),若對方未及時傳回確認訊息,資料就會重新傳遞一次,以確保資料傳輸的完整性。
5. 交談層(Session Layer):
* 一種資料流動的邏輯性通訊路徑(邏輯路徑對比是實體路徑),負責建立或切斷通訊連結/設定傳輸資料的分割等,進行與資料傳輸有關的管理。
* 白話一點說,靠傳輸層的 port 找到對應應用程式後,可以進一步靠 session 連接或切斷時機
* 有很多應用服務運作在交談層上,我們常接觸到的是 NetBIOS names,這是一種用來識別電腦使用 NetBIOS 資源的依據。我們使用Windows 系統時,開啟網路上的芳鄰,或是用到「檔案及列印分享」時,通常會看到群組及電腦名稱,這些就是NetBIOS names定義的。
6. 表現層(Presentation Layer):
* 具體來說,本層就是設備原有的資料表現格式 與 網路共用的資料格式的轉換
* 應用層收到的資料後,透過表現層轉換成適合通訊的資料格式,或將下層傳來的資料轉換成上層可以處理的資料格式
* 例如: 將 ASCII 編碼轉成應用層可以使用的資料,或是處理圖片及其他多媒體檔案,如 JPGE 圖片檔或 MIDI 音效檔,。
* 除了轉檔,有時候當資料透過網路傳輸時,需要將內容予以加密或解密,而這個工作就是在展示層中處理。
7. 應用層(Application Layer):
* 各種我們使用的應用程式中,與通訊有關的部份,常見的通訊協定,有:
* DHCP(Dynamic Host Configuration Protocol)
* FTP(File Transfer Protocol)
* HTTP(HyperText Transfer Protocol)
* POP3(Post Office Protocol-Version 3)
* 依據不同的網路服務方式,這些協定能定義各自的功能及使用規範等細部規則
* 屬於第七層的應用軟體,像是網路瀏覽器(IE、Firefox)、電子郵件、線上遊戲、即時通訊(MSN Messenger、ICQ)等
* 上述軟體均透過單一或多種通訊協定,提供各類網路應用服務,像是網路瀏覽器藉由HTTP的溝通,即可呈現圖文並茂的網頁
## 通訊方式與種類
* 連接導向與非連接導向:
* 連接導向:
* 傳送資料前在兩端主機先建立連線
* 很像再打電話,需要先撥通
* 例如網頁間資訊傳輸
* 非連接導向:
* 不會先進行建立,切斷連接處理
* 傳送端主機隨時可以傳送資料
* 例如:電子郵件
* 因應不同使用場景,兩種方式各有其優缺點
* 電路交換與封包交換:
* 電路交換:
* 利用電話線傳輸,歷史悠久
* 交換機負責中繼處理,連接後線路就被佔用,直到被切斷為止
* 如果多台電腦彼此想利用電路傳送資料的話會出現很多問題
* 封包交換(Packet):
* 為了充分運用網路線路,以及預防網路斷訊風險...等考量,網路傳輸放棄在兩端點的電路交換網絡,改而提出封包交換網絡
* 封包交換是透過**路由器**連接通訊路線,把資料當作封包傳送,路由負責接收
* TCP/IP協定就是採用封包交換來傳遞資料,也就是將資料分拆成無數個小片段,僅在資料片段開頭加上各層的重要資訊(又稱表頭)後,其讓端點負責重組封包並在遺失封包時提出要求
* 這大幅簡化網路本身功能的舉動反而成功整合了各種不同的網絡。
## TCP/IP 網路協定
* TCP/IP:TPC/IP的前身是一個為了驗證封包交換技術而建立的實驗性網路,後來才發展初TCP/IP,其算是一種比較務實的分層架構,也可以視為OSI 7層模型的簡化,其每一層的功能大致可以互相對應。廣義來說,TCP/IP 就是以**IP網路層**協定為基礎,往上層另外延伸的協定集合總稱,所以其不只是某一個協定名稱而已。
* 網際網路(Internet)與TCP/IP關係:之前提過網際網路就是連結所有設備形成一個大龐大網路,想藉由網際網路進行通訊時,就需要使用協定,而TCP/IP就是為了使用網際網路而開發的協定。
## TCP/IP層級說明:
***OSI vs TCP/IP***
![OSI vs TCP/IP](https://i.imgur.com/1AL9fbn.jpg)
* 硬體:TCP/IP最下層是負責物理傳輸的硬體,這硬體是指乙太網路、電話線路或是其他無線設備...等實體層。
* 網路界面層:類比OSI的資料連結層,是利用乙太網路...等的資料連結,進行通訊的界面層級,可以視為是啟動網路卡(NIC)的驅動程式。
* 網際網路層:相當於OSI的網路層,其IP協定(Internet Protocol)就是TCP/IP協議的最重要基礎,其就是跨網路傳送封包,將封包傳送到整個網際網路的協定,IP協定下可以根據IP位址讓網路任兩台電腦互相連結並傳遞封包,我們常聽到的路由器就是以IP位址為主的交換器,其可以根據IP轉發封包,或讓不同的資料連結。此外,IP協定下傳送封包並沒有保證資料傳送的完整行,是屬於缺乏可靠性的協定,這需要其他協定來補足。
* ICMP(Internet Control Message Protocol): 傳送IP封包出現問題時會提出異常通知的協定,有時會用來診斷網路狀態。
* ARP(Address Resolution Protocol):從IP位址取的封包傳送端物理位址(MAC)的協定。
* 傳輸層:傳輸層就是基於IP層上,進一步建立各種應用程式間的通訊協定(Email, HTTP, FTP...等),而連接埠編號(Port)就是用來辨別應用程式用的,其可以視為應用程式的位址,TCP/IP有兩個最具代表性的傳輸協定,就是 TCP & UDP:
* TCP(Transmission Control Protocol):連接導向且具有可靠性的傳輸協定,能確保兩端主機的資料都可以正確傳輸,也因此會產生很多確認機制,也因此較不適合視訊/聲音/影像...等一定時間內要傳輸一定資料量的通訊。
* UDP(User Datagram Protocol):屬於非連接導向且沒有可靠性的傳輸層協定,非常適合影像或聲音...等多媒體通訊。
* 應用層:TCP/IP層級模型中,將OSI的交談層/表現層/應用層...等功能,全部交給應用程式來處理,以下以網頁應用為例:
* WWW:是將網際網路上的資料以超文字(HyperText)形式呈現在瀏覽器上的系統,也是讓網際網路普及的重要動力。
* HTML:就是這系統上主要的共用資料格式,透過瀏覽器,可將HTML文件主體內容作解析後,進行畫面並呈現給使用者。
* HTTP:就是定義上述HTTP資料傳輸方式的通訊協定,整體架構於TCP/IP之上,其特色是基於請求/回應模式,以及無狀態協定...等特色。
以上是瀏覽器網頁的相關應用層協定; 其他像發信時會用SMTP; 收信時會用POP3...等不同的應用層協定。
## TCP/IP資料傳送流程:
***TCP/IP Flow***
![](https://i.imgur.com/MCCctRC.jpg)
以上圖為例,以下簡述TCP/IP資料傳送流程,
1. 最上層使用者注重的是文字內容的表達,而在按下傳送後,E-mail應用程式處理通訊部份就開始工作,應用程式會決定這封信該怎麼使用下層TCP的協定來傳送,例如:是整間公司累積5封信後一起傳送?還是一封一封各自傳送,Email是否要依照特定格式去寫...等,都是應用層的決定範圍。
2. 下層TCP協定接收到上層信件的資料後,開始將資料處理成封包並加上TCP的表頭後往下IP層傳遞,而TCP這裡主要的功用就是建立讓這資料可以在相通的E-mail程式去通訊,並且為了保證所有封包對方都可以收的到,TCP另外會先確認對方是否有連線,並且在最後確認封包都有收到沒有遺漏...等,這些動作都是IP層沒有作到的。
3. IP層接收到資料後會加上IP層的表頭,並且想辦法把資料送到對方的電腦(非應用程式),當中怎麼靠IP找到對方電腦都是IP層負責處理的,可以想像成IP層就像電話,其負責可以連到另一個電話,但聲音要怎麼保證清楚的傳過去則是靠上層的TCP協定處理。
4. IP層以下就是電腦資料透過網卡將資料傳到網路(線)的物理機制了。
## 什麼是 Socket(套接字):
乾貨: [Socket Programming in Python (Guide)](https://realpython.com/python-sockets/)
* 學習網路通訊編程,常常是以Socket套件操作開始,其實Socket不是一個層,最初是UNIX系統下利用網路通訊的一種API,本質上就是一個介面程式(Interface),介於TCP層和應用層之間,目的是把TCP/IP封裝好,讓應用層的協定可以方便快速的使用TCP/IP協定; 以一般的程式操作角度來看,大家可以把Socket當作是(抽象為)對於檔案I/O的一個操作
***socket***
![](https://i.imgur.com/YEY2Hgn.jpg)
以下是用Python的Socket模組建立簡單的Client & Server互動範例:
![](https://i.imgur.com/Eql1Dtc.jpg)
[Simple TCP server by Python Socket Module](https://github.com/EricYangsw/tcp_ip/blob/master/server_client/simple_tcp_server.ipynb)
```Python
#python3
import sys
import socket
import threading
# Simple TCP Server
bind_ip = "0.0.0.0"
bind_port = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(5)
print("[*] Listening on %s:%d" %(bind_ip, bind_port))
def handle_client(client_socket):
request = client_socket.recv(1024)
print("[*] Received: %s" % request)
client_socket.send(b'ACK!')
client_socket.close()
while True:
client, addr = server.accept()
print("[*] Accpeted connection from: %s:%d" % (addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()
# Showing port number in ubuntu system
!netstat -t -u -a -p # On jupyter notebook
$ netstat -t -u -a -p #On bash
```
[Simple TCP Client by Python Socket Module](https://github.com/EricYangsw/tcp_ip/blob/master/server_client/simple_tcp_client.ipynb)
```Python
import sys
import socket
import threading
# Connect to google webpage
target_host = "www.google.com"
target_port = 80
# build socket object:
# AF_INET = IPv4; SOCK_STREAM = TCP
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target_host, target_port))
client.send(b'GET / HTTP/1.1\r\nHost: google.com\r\n\r\n')
response = client.recv(4096)
print(response)
# Connect to ourself server
target_host = "0.0.0.0"
target_port = 9999
# build socket object:
# AF_INET = IPv4; SOCK_STREAM = TCP
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target_host, target_port))
client.send(b'Try to connect to server yaya~~~')
response = client.recv(4096)
print(response)
```
## 其他IP相關重要知識:
1. IPv4 & IPv6: IPv4是目前最普遍的IP層協定的格式,其是由4個小於255的數字組成(EX:255.255.255.255),以二進位表示的話,可以算出總共有2的32次方的組合,而這數字在現今網路世界已經快不夠用(想像成電話號碼不夠每個電話配一個號碼了),雖然有各種虛擬IP位址的技術出現,但還是無法解決這問題,因此IPv6的出現最主要就是為了解決這個問題,只是IPv6目前尚未完全普及。
2. DNS(Domain Name System):平常使用網路時,大部分時間都不會碰到IP位址,這是因為我們建立起字元與IP位址的對應關係,也就是域名,而這對應的系統就是DNS,這樣IP位址就可以轉換成我們人類比較好記的形式,我們在瀏覽器輸入網址的時候,www之後的域名都會透過DNS轉成對易的主機IP。
3. URI(Uniform Resource Identifier):是呈現資源的表記方法,在早期,是先有URL(Uniform Resource Locator)和URN(Uniform Resource Name),後來才全部整合進URI,也就是說URL和URN是URI的子集合。
* URL:主要目的是以文字方式說明網路上的資源如何取得,格式範例如下:
* 通用 : < scheme >:< scheme-specific-part >
* HTTP: http:openhome.cc:8080/Gossip/incex.html
* URN:代表某個資源獨一無二的名稱,早期主要語法格式如下:
* < URN > ::="urn:"< NID > ":" < NSS >
* urn:isbn:978-986-476-675-8 (EX: 書的國際標準書號)
* URI:
* URI = scheme ":" hier-part ["?" query] [ "#" fragment ]
hier-part = "//" or "/"
* foo://example.com:8042/over/there?name=ferret#nose
4. URI(URL) 和 DNS 關係:當URI解析出域名後,需要靠DNS將域名解析出對應IP,如果才能靠協定找到對應的主機。
[URL、域名、DNS解析](https://www.jianshu.com/p/ecdc9abb13d5)
# Python 爬蟲
---
## 基本觀念:
爬蟲基本動作可以歸納為以下循環:
1. 取得網站的 HTML:
* 一個網頁本質上就是一堆 HTML文字,根據 URL透過 Requests送出請求取得 HTML內容。
2. 解析資料以取得目標資訊:
* 透過瀏覽器的開發者工具,觀察目標資訊位置
* 透過 BeautifulSoup(Python tool) 解析 HTML
* 將資料以某種格式(CSV, JSON)寫入或是存到資料庫
3. 堤取頁面中的鏈結:
資料往往不只在一個頁面,因此必須分析出其他連結,在繼續進行分析後爬取目標內容。
## Scrapy 爬蟲軟體
Scrapy是一個用 Python撰寫,基於 **Twisted**網路引擎框架,的開源網路爬蟲架構,幾個主要依賴套件如下:
* lxml: 一個高效率的XML/HTML解析套件
* parsel: 基於 lxml的 XML/HTML的資料探索庫
* w3lib: 處理 URLs和網頁編碼的多用途協助程序
* twisted: 非同步網路引擎框架
* cryptography & pyOpenSSL: 處理各種網路層級安全需求
### Scrapy install
```bash
# install scrapy
$ pip install scrapy
# by anaconda
$ conda install -c conda-forge scrapy
# Test in shell
$ scrapy
Scrapy 1.5.2 - no active project
Usage:
scrapy <command> [options] [args]
Available commands:
bench Run quick benchmark test
fetch Fetch a URL using the Scrapy downloader
genspider Generate new spider using pre-defined templates
runspider Run a self-contained spider (without creating a project)
settings Get settings values
shell Interactive scraping console
startproject Create new project
version Print Scrapy version
view Open URL in browser, as seen by Scrapy
[ more ] More commands available when run from project directory
Use "scrapy <command> -h" to see more info about a command
```
```python
# Check scrapy in python script
>>> import scrapy
>>> scrapy.version_info
(1.5.2)
```
### Simple Scrapy tutorial
這裡用一個專門練習爬蟲的網站 http://books.toscrape.com/ 上爬取輸資訊, 先分析一下我們想爬的資訊,用 Chrome進入網頁後,可以對任何一個書籍圖示點右鍵後,點選「inspect」「審查元素」,
![](https://i.imgur.com/3YXwFNH.jpg)
網頁最下面的**NEXT**也一樣動作:
![](https://i.imgur.com/1afLG4m.jpg)
發現我們要的書籍資訊在
* < article class="product_pod" >
* 書名:h3 > a元素的 **title屬性**
* 書價:< p class="price_color">元素的**文字**中
* 下一頁: ul.pager>li.next>a元素的**href**屬性中
以下是最基本爬蟲實現:
```bash
# 第一步:
# 會產生一個專案,名字是 example (會產生 example資料夾)
# 所以開始前可以先cd到你想測試爬蟲的資料夾
$ scrapy startproject example
New Scrapy project 'example', using template directory '/home/eric/anaconda3/envs/scrapy/lib/python3.6/site-packages/scrapy/templates/project', created in:
/home/eric/coding/python/py_internet/scrapy/example
You can start your first spider with:
cd example
scrapy genspider example example.com
#顯示專案資料夾結構
$ tree example
example
├── example
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── __pycache__
│ ├── settings.py
│ └── spiders
│ ├── __init__.py
│ └── __pycache__
└── scrapy.cfg
# 到你自己喜歡的資料夾
$ cd ./example./example/spiders
# 產生一個 python檔來實現爬充
# (這裡用vim, 但你可以用你自己的編輯器)
$ vim book_spider.py
# .py 檔內容在下一個區塊顯示
# 完成 .py檔後執行
$ scrapy crawl books -o books.csv
```
```python
# book_spider.py
# -*- coding: utf-8 -*-
import scrapy
class BookSpider(scrapy.Spider):
# 每個爬蟲唯一標識(就是上面執行指令的 books)
name = "books"
# 爬蟲起始網址
start_urls = ['http://books.toscrape.com/']
def parse(self, response):
# 分析網頁,書資訊在<article > 元素中
# 用 css() 方法去找所有這樣元素
for book in response.css('article.product_pod'):
# 書名位置
name = book.xpath('./h3/a/@title').extract_first()
# 價錢位置
price = book.css('p.price_color::text').extract_first()
yield {'name': name,
'price': price,}
# 找 NEXT 下一頁的連結
next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
if next_url:
next_url = response.urljoin(next_url)
yield scrapy.Request(next_url, callback=self.parse)
```
幾個小結論:
1. 以上顯示 Scrapy已經高度封裝好很多細節
2. **name** 屬性在一個專案下是唯一標識(這裡是 "books")
3. **start_urls** 屬性是每一個爬蟲起始位置
4. **parse** 方法是scrapy回呼解析函數,主要是分析資料(XPath/CSS)和其他連結下載請求