撰寫各種資料格式的自訂分類器 - AWS Glue

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

撰寫各種資料格式的自訂分類器

您可以提供自訂分類器,分類在 AWS Glue中的資料。您可以使用 grok 模式、XML標籤、 JavaScript 物件符號 () 或逗號分隔值 (JSON) 來建立自訂分類器。CSVAWS 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 EMR、Amazon 或 Redshift 頻譜使用,請查看這些服務的相關文件,以取得有關. 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 模式每次只能處理一行。不支援多行模式。此外,不支援在模式中的換行。

grok 分類器的自定義值

當您定義 grok 分類器時,您可以提供以下值來創建自定義分類器。

名稱

分類器名稱。

分類

寫入的字串用於描述分類資料的格式;例如 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 提供許多常見的模式,您可用來建立自訂分類器。您將一個具名模式新增到分類器定義中的 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義分類器,您可以指定用於定義行的標籤名稱。

分類器的自定義分類器值 XML

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

名稱

分類器名稱。

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

名稱

分類器名稱。

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數據遵循從 http://everypolitician.org/ s3://awsglue-datasets/examples/us-legislators/all/areas.json 繪製的示例JSON文件的模式。檔案中的範例物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

不過,若只要使用 "id" 物件建立結構描述,請建立自訂JSON分類器,並將JSON路徑指定為$.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檔案中「name」陣列中的「other_names」欄位) 建立資料表,您可以建立自訂JSON分類器並將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中設定用 SerDe 於處理,這將在資料目錄中套用。

當您建立自訂分類器時,您也可以針對不同的爬蟲程式重複使用分類器。

  • 對於只有標題(沒有數據)的 csv 文件,這些文件將被歸類為,UNKNOWN因為沒有提供足夠的信息。如果您在列標題選項中指定 CSV「有標題」並提供數據類型,我們可以正確地對這些文件進行分類。

您可以使用自訂CSV分類器來推斷各種資料類型的結構描述。CSV您可以為分類器提供的自訂屬性包括分隔符號、選CSV SerDe 項、關於標題的選項,以及是否對資料執行某些驗證。

AWS Glue 中的自訂分類器值

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

分類器名稱

分類器名稱。

CSV塞爾德

設置CSV在 SerDe 分類器,這將在數據目錄中應用的處理。選項有「開放」CSV SerDe、「懶惰簡單 SerDe」和「無」。當您希望爬蟲程式執行偵測時,您可以指定「無」值。

欄位分隔符號

表示用於分隔資料列中每個欄位項目的自訂符號。提供 Unicode 字元。如果無法輸入分隔符號,您可以複製並貼上它。這個方式適用於可列印字元,包括系統不支援的字元 (通常顯示為 □)。

引號符號

用來表示將內容結合成單一欄位值的自訂符號。必須不同於欄位分隔符號。提供 Unicode 字元。如果無法輸入分隔符號,您可以複製並貼上它。這個方式適用於可列印字元,包括系統不支援的字元 (通常顯示為 □)。

欄位標題

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

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

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

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

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

自訂資料類型 - 選用

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