撰寫自訂分類器 - AWS Glue

撰寫自訂分類器

您可以提供自訂分類器,分類在 AWS Glue 中的資料。您可以使用 grok 模式、XML 標籤、JavaScript Object 符號 (JSON) 或逗號分隔值 (CSV),建立自訂分類器。AWS Glue 爬蟲程式呼叫自訂分類器。如果分類器能夠辨識資料,它會將資料的分類和結構描述傳回爬蟲程式。如果您的資料不符合任何內建的分類器,或者想要自訂由爬蟲程式建立的資料表,那麼您可能需要定義自訂分類器。

如需使用 AWS Glue 主控台建立分類器的詳細資訊,請參閱在 AWS Glue 主控台上使用分類器

AWS Glue 會依照您指定的順序,在內建的分類器之前執行自訂分類器。當爬蟲程式找到符合資料的分類器時,分類字串和結構描述將用於資料表的定義中,這些資料表將寫入至您的 AWS Glue Data Catalog。

撰寫 grok 自訂分類器

Grok 是一種工具,用於剖析指定相符模式的文字資料。grok 模式是一組命名規則表達式 (regex), 用於每次比對一行。AWS Glue 使用 grok 模式來推斷資料的結構描述。當 grok 模式符合您的資料時,AWS Glue 將使用此模式判斷您資料的結構,並將其映射到欄位。

AWS Glue 提供許多內建模式,或者您可以定義自己的模式。您可以在自訂分類器定義中使用內建模式和自訂模式來建立 grok 模式。您可以量身打造 grok 模式來分類自訂文字檔案格式。

注意

針對 AWS Glue Data Catalog 中建立的資料表,AWS Glue Grok 自訂分類器會使用 GrokSerDe 序列化程式庫。因此,如果您正在使用 AWS Glue Data Catalog 搭配 Amazon Athena、Amazon EMR 或 Redshift Spectrum,則請參閱這些服務的文件,以取得 GrokSerDe 的支援資訊。目前,當您從 Amazon EMR 和 Redshift 查詢利用 GrokSerDe 建立的資料表時,可能會遇到問題。

以下是 grok 模式元件的基本語法:

%{PATTERN:field-name}

符合具名的 PATTERN 的資料會映射到結構描述中的 field-name 欄位符合,預設資料類型為 string。除此之外,您亦可選擇在產生的結構描述中,將欄位的資料類型轉換為 bytebooleandoubleshortintlongfloat

%{PATTERN:field-name:data-type}

例如,若要將 num 欄位轉換為 int 資料類型,您可以使用此模式:

%{NUMBER:num:int}

模式可由其他模式組成。舉例而言,您可使用月、日及時間的模式來定義 SYSLOG 時間戳記的模式 (例如 Feb 1 06:25:43)。您能夠使用下列模式來定義此資料:

SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME}
注意

Grok 模式每次只能處理一行。不支援多行模式。此外,不支援在模式中的換行。

AWS Glue 中的自訂分類器值

當您定義 grok 分類器時,您將以下值提供至 AWS Glue 以建立自訂分類器。

Name

分類器名稱。

分類

寫入的字串用於描述分類資料的格式;例如 special-logs

Grok 模式

套用到資料存放區的一組模式可判斷是否符合。這些模式皆來自 AWS Glue 內建模式,以及您所定義的任何自訂模式。

以下為 grok 模式的範例:

%{TIMESTAMP_ISO8601:timestamp} \[%{MESSAGEPREFIX:message_prefix}\] %{CRAWLERLOGLEVEL:loglevel} : %{GREEDYDATA:message}

當資料符合 TIMESTAMP_ISO8601,將會建立結構描述欄位 timestamp。此行為類似範例中的其他具名模式。

自訂模式

您定義的選用自訂模式。分類您的資料的 grok 模式會參考這些模式。您可以在套用至您資料的 grok 模式中參考這些自訂模式。每個自訂元件模式都必須位於不同的行。規則表達式 (regex) 語法可用來定義模式。

以下是使用指定模式的範例:

CRAWLERLOGLEVEL (BENCHMARK|ERROR|WARN|INFO|TRACE) MESSAGEPREFIX .*-.*-.*-.*-.*

當資料符合其中一個列舉字串時,第一個自訂具名模式 CRAWLERLOGLEVEL 即為相符。第二個自訂模式 MESSAGEPREFIX 嘗試符合訊息字首字串。

AWS Glue 追蹤建立時間、上次更新時間和您的分類器版本。

AWS Glue 內建模式

AWS Glue 提供許多常見的模式,您可用來建立自訂分類器。您將一個具名模式新增到分類器定義中的 grok pattern

以下清單包含各個模式的一行。在每一行中,模式名稱之後是它的定義。規則表達式 (regex) 語法可用來定義模式。

#<noloc>&GLU;</noloc> Built-in patterns USERNAME [a-zA-Z0-9._-]+ USER %{USERNAME:UNWANTED} INT (?:[+-]?(?:[0-9]+)) BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))) NUMBER (?:%{BASE10NUM:UNWANTED}) BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+)) BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b BOOLEAN (?i)(true|false) POSINT \b(?:[1-9][0-9]*)\b NONNEGINT \b(?:[0-9]+)\b WORD \b\w+\b NOTSPACE \S+ SPACE \s* DATA .*? GREEDYDATA .* #QUOTEDSTRING (?:(?<!\\)(?:"(?:\\.|[^\\"])*"|(?:'(?:\\.|[^\\'])*')|(?:`(?:\\.|[^\\`])*`))) QUOTEDSTRING (?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``)) UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12} # Networking MAC (?:%{CISCOMAC:UNWANTED}|%{WINDOWSMAC:UNWANTED}|%{COMMONMAC:UNWANTED}) CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}) WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2}) COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}) IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)? IPV4 (?<![0-9])(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))(?![0-9]) IP (?:%{IPV6:UNWANTED}|%{IPV4:UNWANTED}) HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-_]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-_]{0,62}))*(\.?|\b) HOST %{HOSTNAME:UNWANTED} IPORHOST (?:%{HOSTNAME:UNWANTED}|%{IP:UNWANTED}) HOSTPORT (?:%{IPORHOST}:%{POSINT:PORT}) # paths PATH (?:%{UNIXPATH}|%{WINPATH}) UNIXPATH (?>/(?>[\w_%!$@:.,~-]+|\\.)*)+ #UNIXPATH (?<![\w\/])(?:/[^\/\s?*]*)+ TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+)) WINPATH (?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+ URIPROTO [A-Za-z]+(\+[A-Za-z+]+)? URIHOST %{IPORHOST}(?::%{POSINT:port})? # uripath comes loosely from RFC1738, but mostly from what Firefox # doesn't turn into %XX URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%_\-]*)+ #URIPARAM \?(?:[A-Za-z0-9]+(?:=(?:[^&]*))?(?:&(?:[A-Za-z0-9]+(?:=(?:[^&]*))?)?)*)? URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]* URIPATHPARAM %{URIPATH}(?:%{URIPARAM})? URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})? # Months: January, Feb, 3, 03, 12, December MONTH \b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b MONTHNUM (?:0?[1-9]|1[0-2]) MONTHNUM2 (?:0[1-9]|1[0-2]) MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]) # Days: Monday, Tue, Thu, etc... DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?) # Years? YEAR (?>\d\d){1,2} # Time: HH:MM:SS #TIME \d{2}:\d{2}(?::\d{2}(?:\.\d+)?)? # TIME %{POSINT<24}:%{POSINT<60}(?::%{POSINT<60}(?:\.%{POSINT})?)? HOUR (?:2[0123]|[01]?[0-9]) MINUTE (?:[0-5][0-9]) # '60' is a leap second in most time standards and thus is valid. SECOND (?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?) TIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9]) # datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it) DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR} DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR} DATESTAMP_US %{DATE_US}[- ]%{TIME} DATESTAMP_EU %{DATE_EU}[- ]%{TIME} ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE})) ISO8601_SECOND (?:%{SECOND}|60) TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}? TZ (?:[PMCE][SD]T|UTC) DATESTAMP_RFC822 %{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ} DATESTAMP_RFC2822 %{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE} DATESTAMP_OTHER %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR} DATESTAMP_EVENTLOG %{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND} CISCOTIMESTAMP %{MONTH} %{MONTHDAY} %{TIME} # Syslog Dates: Month Day HH:MM:SS SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME} PROG (?:[\w._/%-]+) SYSLOGPROG %{PROG:program}(?:\[%{POSINT:pid}\])? SYSLOGHOST %{IPORHOST} SYSLOGFACILITY <%{NONNEGINT:facility}.%{NONNEGINT:priority}> HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT} # Shortcuts QS %{QUOTEDSTRING:UNWANTED} # Log formats SYSLOGBASE %{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource} %{SYSLOGPROG}: MESSAGESLOG %{SYSLOGBASE} %{DATA} COMMONAPACHELOG %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{Bytes:bytes=%{NUMBER}|-}) COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent} COMMONAPACHELOG_DATATYPED %{IPORHOST:clientip} %{USER:ident;boolean} %{USER:auth} \[%{HTTPDATE:timestamp;date;dd/MMM/yyyy:HH:mm:ss Z}\] "(?:%{WORD:verb;string} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion;float})?|%{DATA:rawrequest})" %{NUMBER:response;int} (?:%{NUMBER:bytes;long}|-) # Log Levels LOGLEVEL ([A|a]lert|ALERT|[T|t]race|TRACE|[D|d]ebug|DEBUG|[N|n]otice|NOTICE|[I|i]nfo|INFO|[W|w]arn?(?:ing)?|WARN?(?:ING)?|[E|e]rr?(?:or)?|ERR?(?:OR)?|[C|c]rit?(?:ical)?|CRIT?(?:ICAL)?|[F|f]atal|FATAL|[S|s]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)

撰寫 XML 自訂分類器

XML 會利用檔案中的標籤來定義文件的結構。使用 XML 自訂分類器,您可以指定用來定義一個列的標籤名稱。

AWS Glue 中的自訂分類器值

當您定義 XML 分類器時,您將以下值提供至 AWS Glue 以建立分類器。此分類器的分類欄位設定為 xml

Name

分類器名稱。

Row 標籤

在 XML 文件中用於定義資料表列的 XML 標籤名稱,不含角括號 < >。此名稱必須符合 XML 的標籤規則。

注意

包含列資料的元素不得為自我封閉的空元素。舉例而言, 不會AWS Glue剖析此空元素:

<row att1=”xx” att2=”yy” />

空元素可撰寫如下:

<row att1=”xx” att2=”yy”> </row>

AWS Glue 追蹤建立時間、上次更新時間和您的分類器版本。

例如,假設您擁有以下 XML 檔案。若要建立僅含有作者和標題的 AWS Glue 資料表,請在 AWS Glue 主控台中以 Row 標籤做為 AnyCompany 來建立分類器。接著,新增並執行採用此自訂分類器的爬蟲程式即可。

<?xml version="1.0"?> <catalog> <book id="bk101"> <AnyCompany> <author>Rivera, Martha</author> <title>AnyCompany Developer Guide</title> </AnyCompany> </book> <book id="bk102"> <AnyCompany> <author>Stiles, John</author> <title>Style Guide for AnyCompany</title> </AnyCompany> </book> </catalog>

撰寫 JSON 自訂分類器

JSON 是資料交換格式。它定義資料結構與名稱值組或值的排序清單。使用 JSON 自訂分類器時,您可以指定資料結構的 JSON 路徑,以用於定義資料表的結構描述。

AWS Glue 中的自訂分類器值

當您定義 JSON 分類器時,您將以下值提供至 AWS Glue 以建立分類器。此分類器的分類欄位設定為 json

Name

分類器名稱。

JSON 路徑

JSON 路徑會指向用來定義資料表結構描述的物件。您可以用點標記法或括號標記法來撰寫 JSON 路徑。以下是支援的運算子:

運算子 描述
$ JSON 物件的根元素。這會啟動所有路徑表達式
* 萬用字元。可在 JSON 路徑中用於需要名稱或數字的任何位置。
.<name> 以點標記的子代。指定 JSON 物件中的子欄位。
['<name>'] 以刮號標記的子代。指定 JSON 物件中的子欄位。您只能指定一個子欄位。
[<number>] 陣列索引。以索引指定陣列的值。

AWS Glue 追蹤建立時間、上次更新時間和您的分類器版本。

範例 使用 JSON 分類器從陣列中提取記錄

此處會假設您的 JSON 資料是一系列的記錄。舉例來說,檔案的前面幾行可能如下所示:

[ { "type": "constituency", "id": "ocd-division\/country:us\/state:ak", "name": "Alaska" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:1", "name": "Alabama's 1st congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:2", "name": "Alabama's 2nd congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:3", "name": "Alabama's 3rd congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:4", "name": "Alabama's 4th congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:5", "name": "Alabama's 5th congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:6", "name": "Alabama's 6th congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:al\/cd:7", "name": "Alabama's 7th congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:ar\/cd:1", "name": "Arkansas's 1st congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:ar\/cd:2", "name": "Arkansas's 2nd congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:ar\/cd:3", "name": "Arkansas's 3rd congressional district" }, { "type": "constituency", "id": "ocd-division\/country:us\/state:ar\/cd:4", "name": "Arkansas's 4th congressional district" } ]

透過內建 JSON 分類器執行爬蟲程式時,即可將整個檔案用來定義結構描述。因為您尚未 JSON 路徑,該爬蟲程式會將資料視為一個物件,亦即只是一個陣列。例如,結構描述看起來類似如下:

root |-- record: array

然而,若要在 JSON 陣列中根據每個記錄建立結構描述,請建立自訂 JSON 分類器並指定 JSON 路徑為 $[*]。當您指定此 JSON 路徑時,分類器會詢問陣列中的 12 筆記錄以判斷結構描述。產生的結構描述將包含各個物件的獨立欄位,如以下範例所示:

root |-- type: string |-- id: string |-- name: string

範例 使用 JSON 分類器僅檢查檔案的部分

此處假設 JSON 資料會遵循範例 JSON 檔案 s3://awsglue-datasets/examples/us-legislators/all/areas.json 的模式,該檔案取自 http://everypolitician.org/。JSON 檔案中的範例物件看起來會像下述內容:

{ "type": "constituency", "id": "ocd-division\/country:us\/state:ak", "name": "Alaska" } { "type": "constituency", "identifiers": [ { "scheme": "dmoz", "identifier": "Regional\/North_America\/United_States\/Alaska\/" }, { "scheme": "freebase", "identifier": "\/m\/0hjy" }, { "scheme": "fips", "identifier": "US02" }, { "scheme": "quora", "identifier": "Alaska-state" }, { "scheme": "britannica", "identifier": "place\/Alaska" }, { "scheme": "wikidata", "identifier": "Q797" } ], "other_names": [ { "lang": "en", "note": "multilingual", "name": "Alaska" }, { "lang": "fr", "note": "multilingual", "name": "Alaska" }, { "lang": "nov", "note": "multilingual", "name": "Alaska" } ], "id": "ocd-division\/country:us\/state:ak", "name": "Alaska" }

透過內建 JSON 分類器執行爬蟲程式時,即可將整個檔案用來建立結構描述。您得到的結構描述可能類似:

root |-- type: string |-- id: string |-- name: string |-- identifiers: array | |-- element: struct | | |-- scheme: string | | |-- identifier: string |-- other_names: array | |-- element: struct | | |-- lang: string | | |-- note: string | | |-- name: string

不過,您必須建立自訂 JSON 分類器並將 JSON 路徑指定為 id,才能僅使用「$.id」物件建立結構描述。如此一來,系統僅會依據「id」欄位來產生結構描述:

root |-- record: string

使用此結構描述所擷取的前幾行資料如下所示:

{"record": "ocd-division/country:us/state:ak"} {"record": "ocd-division/country:us/state:al/cd:1"} {"record": "ocd-division/country:us/state:al/cd:2"} {"record": "ocd-division/country:us/state:al/cd:3"} {"record": "ocd-division/country:us/state:al/cd:4"} {"record": "ocd-division/country:us/state:al/cd:5"} {"record": "ocd-division/country:us/state:al/cd:6"} {"record": "ocd-division/country:us/state:al/cd:7"} {"record": "ocd-division/country:us/state:ar/cd:1"} {"record": "ocd-division/country:us/state:ar/cd:2"} {"record": "ocd-division/country:us/state:ar/cd:3"} {"record": "ocd-division/country:us/state:ar/cd:4"} {"record": "ocd-division/country:us/state:as"} {"record": "ocd-division/country:us/state:az/cd:1"} {"record": "ocd-division/country:us/state:az/cd:2"} {"record": "ocd-division/country:us/state:az/cd:3"} {"record": "ocd-division/country:us/state:az/cd:4"} {"record": "ocd-division/country:us/state:az/cd:5"} {"record": "ocd-division/country:us/state:az/cd:6"} {"record": "ocd-division/country:us/state:az/cd:7"}

若要根據 JSON 檔案中的深度巢狀物件 (例如「identifier」) 來建立結構描述,則可建立自訂 JSON 分類器並將 JSON 路徑指定為 $.identifiers[*].identifier。儘管產生的結構描述與先前範例類似,但它是依據 JSON 檔案中不同的物件建立而成。

結構描述看起來類似如下:

root |-- record: string

若列出資料表的前面幾行,即會顯示以「identifier」物件中資料為基礎的結構描述:

{"record": "Regional/North_America/United_States/Alaska/"} {"record": "/m/0hjy"} {"record": "US02"} {"record": "5879092"} {"record": "4001016-8"} {"record": "destination/alaska"} {"record": "1116270"} {"record": "139487266"} {"record": "n79018447"} {"record": "01490999-8dec-4129-8254-eef6e80fadc3"} {"record": "Alaska-state"} {"record": "place/Alaska"} {"record": "Q797"} {"record": "Regional/North_America/United_States/Alabama/"} {"record": "/m/0gyh"} {"record": "US01"} {"record": "4829764"} {"record": "4084839-5"} {"record": "161950"} {"record": "131885589"}

您可以建立自訂 JSON 分類器並將 JSON 路徑指定為 $.other_names[*].name,藉此根據 JSON 檔案中其他深度巢狀物件 (例如「other_names」陣列中的「name」欄位) 來建立資料表。儘管產生的結構描述與先前範例類似,但它是依據 JSON 檔案中不同的物件建立而成。結構描述看起來類似如下:

root |-- record: string

若列出資料表的前面幾行,即會顯示以「name」陣列中「other_names」物件資料為基礎的結構描述:

{"record": "Alaska"} {"record": "Alaska"} {"record": "Аляска"} {"record": "Alaska"} {"record": "Alaska"} {"record": "Alaska"} {"record": "Alaska"} {"record": "Alaska"} {"record": "Alaska"} {"record": "ألاسكا"} {"record": "ܐܠܐܣܟܐ"} {"record": "الاسكا"} {"record": "Alaska"} {"record": "Alyaska"} {"record": "Alaska"} {"record": "Alaska"} {"record": "Штат Аляска"} {"record": "Аляска"} {"record": "Alaska"} {"record": "আলাস্কা"}

撰寫 CSV 自訂分類器

自訂 CSV 分類器可讓您在自訂 csv 分類器欄位中為每一欄指定資料類型。您可以指定每欄的資料類型,用逗號分隔。透過指定資料類型,您可以覆寫爬蟲程式推斷的資料類型,並確保資料將適當地分類。當您建立自訂分類器時,您也可以針對不同的爬蟲程式重複使用分類器。

  • 對於只有標題 (沒有資料) 的 csv 檔案,這些檔案將被分類為 UNKNOWN,因為沒有提供足夠的資訊。如果您在 Column headings (欄位標題) 中指定 CSV「具有標題」,並提供資料類型,我們可以正確地對這些檔案進行分類。

您可以使用自訂 CSV 分類器來推論各種 CSV 資料類型的結構描述。您可以為您的分類器提供的自訂屬性,包含分隔符號、標頭相關選項,以及是否要對資料執行特定驗證。

AWS Glue 中的自訂分類器值

當定義 CSV 分類器時,您要將下列值提供至 AWS Glue 以便建立分類器。此分類器的分類欄位設定為 csv

Name

分類器名稱。

欄位分隔符號

表示用於分隔資料列中每個欄位項目的自訂符號。

引號符號

用來表示將內容結合成單一欄位值的自訂符號。必須不同於欄位分隔符號。

欄位標題

指示在 CSV 檔案中應如何偵測出欄位標題的行為。如果您的自訂 CSV 檔案包含欄位標題,請輸入以逗號分隔的欄位標題清單。

處理選項:允許檔案包含單一欄位

啟用處理僅包含一個欄位的檔案。

處理選項:裁剪空格後再識別欄位值

指定在確認欄位值類型之前是否要裁剪值。

自訂資料類型 - 選用

輸入以逗號分隔的自訂資料類型。指定 CSV 檔案中的自訂資料類型。自訂資料類型必須是受支援的資料類型。支援的資料類型為:"BINARY"、"BOOLEAN"、"DATE"、"DECIMAL"、"DOUBLE"、"FLOAT"、"INT"、"LONG"、"SHORT"、"STRING"、"TIMESTAMP"。不受支援的資料類型會顯示錯誤。