正則表達式實戰指南:從基礎到爬蟲應用

目錄

  1. 基礎語法
  2. 常用正則表達式範例
  3. 網頁爬蟲實戰案例
  4. 在 make.com 平台的應用
  5. 實戰技巧與注意事項

基礎語法

正則表達式是一種強大的文本模式匹配工具,以下是基本語法元素的對照表:

字元 說明 實例 匹配結果
. 匹配任意單個字元(除換行符外) a.c abc, adc, a$c…
\d 匹配任意數字 \d{3} 123, 456…
\w 匹配字母、數字或下劃線 \w+ abc, a123, test_123…
\s 匹配空白字元(空格、製表符、換行符) a\sb “a b”, “a\tb”…
^ 匹配字串開頭 ^Hello “Hello world”
$ 匹配字串結尾 world$ “Hello world”
* 匹配前面的模式零次或多次 a*b b, ab, aab…
+ 匹配前面的模式一次或多次 a+b ab, aab…
? 匹配前面的模式零次或一次 colou?r color, colour
{n} 匹配前面的模式恰好n次 a{3} aaa
{n,} 匹配前面的模式至少n次 a{2,} aa, aaa, aaaa…
{n,m} 匹配前面的模式n到m次 a{2,4} aa, aaa, aaaa
` ` 邏輯或 `cat
[] 字元集合,匹配括號內任意字元 [abc] a, b, c
[^] 字元集合,匹配非括號內的任意字元 [^abc] d, e, f…
() 捕獲組,可以提取匹配的內容 (abc) 提取 “abc”
(?:) 非捕獲組,不提取匹配的內容 (?:abc) 不提取 “abc”

匹配模式修飾符

修飾符 說明
g 全局匹配 (找出所有匹配項而非僅第一個)
i 忽略大小寫
m 多行匹配
s 使 . 可以匹配換行符

HTML 提取常用技巧

  1. 最小匹配: .*? 而不是 .* (貪婪匹配)
  2. 屬性匹配: [^>]* 可以匹配標籤內任意屬性
  3. 捕獲組: () 用於提取需要的內容

常用正則表達式範例

以下是 20 個實用的正則表達式範例:

1. 電子郵件地址

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

匹配例子: john.doe@example.com, user123@gmail.co.uk

2. URL

const urlRegex = /^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;

匹配例子: https://www.example.com, example.com/path?query=123

3. 電話號碼 (國際格式)

const phoneRegex = /^\+?(\d{1,3})?[\s-]?\(?\d{1,4}\)?[\s-]?\d{1,4}[\s-]?\d{1,9}$/;

匹配例子: +1 (123) 456-7890, 0912-345-678

4. IP地址 (IPv4)

const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;

匹配例子: 192.168.1.1, 127.0.0.1

5. 日期 (YYYY-MM-DD 格式)

const dateRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;

匹配例子: 2023-01-31, 2022-12-01

6. 時間 (HH:MM:SS 或 HH:MM 格式)

const timeRegex = /^([01]?[0-9]|2[0-3]):([0-5][0-9])(?::([0-5][0-9]))?$/;

匹配例子: 13:45:30, 09:05

7. 密碼強度 (至少8位,包含大小寫字母、數字和特殊字符)

const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;

匹配例子: Password123!, Secure@9876

8. 信用卡號碼

const creditCardRegex = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$/;

匹配例子: 4111111111111111 (Visa), 5500000000000004 (MasterCard)

9. 郵政編碼 (美國)

const usZipCodeRegex = /^\d{5}(?:-\d{4})?$/;

匹配例子: 12345, 12345-6789

10. 社交安全號碼 (美國)

const ssnRegex = /^(?!000|666|9\d{2})([0-8]\d{2}|7([0-6]\d|7[012]))(?!00)\d{2}(?!0000)\d{4}$/;

匹配例子: 123-45-6789

11. HTML 標籤

const htmlTagRegex = /<\/?[a-z][^>]*>/gi;

匹配例子: , ,

12. 提取引號內容

const quotesContentRegex = /"([^"]*)"/g;

匹配例子: 從 ‘He said “hello world”’ 中提取 “hello world”

13. 十六進制顏色代碼

const hexColorRegex = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;

匹配例子: #FF0000, #F00, FF0000

14. 數字範圍驗證 (0-100)

const numberRangeRegex = /^([0-9]|[1-9][0-9]|100)$/;

匹配例子: 0, 42, 100

15. 用戶名 (字母開頭,允許字母、數字、下劃線,長度3-16)

const usernameRegex = /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/;

匹配例子: john_doe123, user_2023

16. 中文字符

const chineseCharRegex = /[\u4e00-\u9fa5]/g;

匹配例子: 你好世界

17. 提取 標籤內容

const scriptContentRegex = /<script[^>]*>([\s\S]*?)<\/script>/gi;

匹配例子: console.log(‘hello’);

18. 提取 CSV 文件中的行

const csvLineRegex = /(?:^|,)(?:"([^"]*(?:""[^"]*)*)"|([^,]*))/g;

匹配例子: 1,“John, Doe”,30

19. 移除多餘空白

const removeExtraSpacesRegex = /\s{2,}/g;

使用例子: “Hello world”.replace(removeExtraSpacesRegex, " “) 得到 “Hello world”

20. 純數字驗證

const digitsOnlyRegex = /^\d+$/;

匹配例子: 12345, 67890

網頁爬蟲實戰案例

Google 新聞搜尋結果提取

以下是用於提取 Google 新聞搜尋結果的正則表達式:

標題正則表達式

const titleRegex = /<h[3-4][^>]*>.*?<a[^>]*>(.*?)<\/a>.*?<\/h[3-4]>/gs;

連結正則表達式

const linkRegex = /<h[3-4][^>]*>.*?<a[^>]*?href="([^"]*)"[^>]*>.*?<\/a>.*?<\/h[3-4]>/gs;

簡介正則表達式

const descriptionRegex = /<div class="[^"]*?st"[^>]*>(.*?)<\/div>|<span class="[^"]*?st"[^>]*>(.*?)<\/span>/gs;

另一種簡介可能的位置

const altDescriptionRegex = /<div class="[^"]*?VwiC3b[^"]*"[^>]*>(.*?)<\/div>/gs;

LinkedIn 職務搜尋結果提取

以下是用於提取 LinkedIn 職務搜尋結果的正則表達式:

職務名稱正則表達式

const jobTitleRegex = /<h3[^>]*class="[^"]*base-search-card__title[^"]*"[^>]*>.*?<a[^>]*>(.*?)<\/a>.*?<\/h3>/gs;

公司名稱正則表達式

const companyNameRegex = /<h4[^>]*class="[^"]*base-search-card__subtitle[^"]*"[^>]*>.*?<a[^>]*>(.*?)<\/a>.*?<\/h4>/gs;

職務連結正則表達式

const jobLinkRegex = /<h3[^>]*class="[^"]*base-search-card__title[^"]*"[^>]*>.*?<a[^>]*?href="([^"]*)"[^>]*>.*?<\/a>.*?<\/h3>/gs;

工作地點正則表達式

const locationRegex = /<span[^>]*class="[^"]*job-search-card__location[^"]*"[^>]*>(.*?)<\/span>/gs;

發布時間正則表達式

const postedTimeRegex = /<time[^>]*>(.*?)<\/time>/gs;

薪資範圍正則表達式 (如果有)

const salaryRegex = /<span[^>]*class="[^"]*job-search-card__salary-info[^"]*"[^>]*>(.*?)<\/span>/gs;

工作類型正則表達式 (全職、兼職等)

const jobTypeRegex = /<li[^>]*class="[^"]*job-search-card__job-type[^"]*"[^>]*>(.*?)<\/li>/gs;

在 make.com 平台的應用

Make.com (前身為 Integromat) 提供了 HTML to text 和 Text parser 模組,可以結合使用這些正則表達式來提取和處理網頁數據。

Google 新聞搜尋結果提取步驟:

  1. 添加 HTTP 模組

    • 設置為 GET 請求並輸入 Google 新聞搜索 URL
  2. 添加 HTML to text 模組

    • 連接到 HTTP 模組的輸出
  3. 添加 Text parser 模組

    • 為標題設置項目,使用 titleRegex
    • 為連結設置項目,使用 linkRegex
    • 為簡介設置項目,使用 descriptionRegex
    • 可選:為另一種簡介格式設置項目,使用 altDescriptionRegex

Text parser 模組設置示例:

  1. 提取標題

    • Pattern type: 選擇 “Regular expression”
    • Pattern: <h[3-4][^>]*>.*?<a[^>]*>(.*?)<\/a>.*?<\/h[3-4]>
    • Output: {{1}}(這會提取第一個捕獲組,即標題文字)
  2. 提取連結

    • Pattern type: 選擇 “Regular expression”
    • Pattern: <h[3-4][^>]*>.*?<a[^>]*?href="([^"]*)"[^>]*>.*?<\/a>.*?<\/h[3-4]>
    • Output: {{1}}(這會提取第一個捕獲組,即連結 URL)
  3. 提取簡介

    • Pattern type: 選擇 “Regular expression”
    • Pattern: <div class="[^"]*?st"[^>]*>(.*?)<\/div>|<span class="[^"]*?st"[^>]*>(.*?)<\/span>
    • Output: {{1}}{{2}}(這會提取第一或第二個捕獲組,取決於哪個匹配)

實戰技巧與注意事項

1. 網站結構變化的應對策略

網站經常更新其 HTML 結構,導致原有的正則表達式無法正常工作。以下是應對策略:

  • 定期檢查和更新正則表達式:設置定期的監控任務
  • 使用更寬鬆的模式:減少對特定 CSS 類名的依賴
  • 實施錯誤處理機制:當提取失敗時有備用方案

2. 爬蟲限制與合規性

大型網站通常有爬蟲限制,需要注意:

  • 遵守網站的使用條款:LinkedIn 和 Google 都有限制自動爬取的條款
  • 控制請求頻率:避免在短時間內發送太多請求
  • 添加適當的 User-Agent:模擬正常的瀏覽器訪問
  • 考慮使用官方 API:如果可能,優先使用官方提供的 API

3. 正則表達式優化技巧

  • 使用非貪婪匹配.*? 而不是 .*
  • 限制匹配範圍:例如使用 ^$ 精確匹配
  • 避免過度複雜:複雜的正則表達式難以維護和調試
  • 分解複雜模式:使用多個簡單的正則表達式而不是一個複雜的

4. 測試與驗證

在實際使用前,確保測試和驗證正則表達式:

  • 使用 regex101.com 等工具:可視化測試正則表達式
  • 小規模測試:先在小樣本上測試
  • 驗證提取結果:確認提取的數據是否正確
  • 添加日誌記錄:記錄匹配和不匹配的情況以便調試

5. 處理特殊情況

  • HTML 實體:處理 &amp;, &lt; 等 HTML 實體
  • 多語言支持:考慮各種語言的字符和編碼
  • 動態加載內容:某些內容可能是通過 JavaScript 動態加載的,無法直接用正則表達式提取