本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
为不同的数据格式编写自定义分类器
您可以提供自定义分类器来对 Amazon Glue中的数据进行分类。您可以使用 grok 模式、XML标签、 JavaScript 对象表示法 (JSON) 或逗号分隔值 () 创建自定义分类器。CSVAmazon Glue 爬网程序调用自定义分类器。如果分类器可识别数据,则它会将数据的分类和架构返回到爬网程序。如果数据与任何内置分类器不匹配,或者您希望自定义由爬网程序创建的表,则可能需要定义自定义分类器。
有关使用 Amazon Glue 控制台创建分类器的更多信息,请参阅使用控制台创建分类器 Amazon Glue。
Amazon Glue 按照您指定的顺序在内置分类器之前运行自定义分类器。当爬网程序找到与数据匹配的分类器时,分类字符串和架构将在写入 Amazon Glue Data Catalog的表的定义中使用。
编写 grok 自定义分类器
Grok 是一个工具,用于分析给定匹配模式的文本数据。grok 模式是一组命名的正则表达式 (regex),用于一次匹配一行数据。Amazon Glue 使用 grok 模式来推断数据的架构。当 grok 模式与您的数据匹配时,Amazon Glue 使用该模式来确定数据的结构并将其映射到字段。
Amazon Glue 提供许多内置模式,或者您也可以定义自己的模式。您可以使用自定义分类器定义中的内置模式和自定义模式来创建 grok 模式。您可以定制 grok 模式来对自定义文本文件格式进行分类。
注意
Amazon Glue grok 自定义分类器对在 Amazon Glue Data Catalog中创建的表使用 GrokSerDe
序列化库。如果您在 Amazon Glue Data Catalog 亚马逊 Athena、EMR Amazon 或 Redshift Spectrum 上使用,请查看有关这些服务的文档,了解有关支持的信息。GrokSerDe
目前,在查询使用GrokSerDe
来自亚马逊EMR和 Redshift Spectrum 的创建的表时,您可能会遇到问题。
以下是 grok 模式组件的基本语法:
%{PATTERN:field-name}
与命名 PATTERN
匹配的数据映射到架构中的 field-name
列,默认数据类型为 string
。或者,该字段的数据类型可以在生成的架构中强制转换为 byte
、boolean
、double
、short
、int
、long
或 float
。
%{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 模式
-
应用于数据存储以确定是否存在匹配的模式集。这些模式来自 Amazon 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
尝试匹配消息前缀字符串。
Amazon Glue 跟踪分类器的创建时间、上次更新时间和版本。
内置图案
Amazon 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分类器时,需要向提供以下值Amazon Glue来创建分类器。此分类器的分类字段设置为 xml
。
- 名称
-
分类器的名称。
- 行标签
-
定义XML文档中表格行的XML标签名称,不带尖括号
< >
。该名称必须符合标签XML规则。注意
包含行数据的元素不能是自结束的空元素。例如, 不Amazon Glue解析此空元素:
<row att1=”xx” att2=”yy” />
可以如下所示编写空元素:
<row att1=”xx” att2=”yy”> </row>
Amazon Glue 跟踪分类器的创建时间、上次更新时间和版本。
例如,假设您有以下XML文件。要创建仅包含作者和标题列的 Amazon Glue 表,请在 Amazon Glue 控制台中创建 Row tag (行标签) 为 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路径。
Amazon Glue 中的自定义分类器值
定义JSON分类器时,需要向提供以下值Amazon Glue来创建分类器。此分类器的分类字段设置为 json
。
- 名称
-
分类器的名称。
- JSON路径
-
指向用于定义表架构的对象的JSON路径。JSON路径可以用点符号或方括号表示法书写。支持以下运算符:
运算符 描述 $
JSON对象的根元素。这将启动所有路径表达式 *
通配符。JSON路径中需要名称或数字的任何地方都可用。 .<name>
点表示的子字段。在JSON对象中指定子字段。 ['<name>']
括号表示的子字段。指定JSON对象中的子字段。只能指定单个子字段。 [<number>]
数组索引。按索引指定数组的值。
Amazon 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 分类器字段中的每列指定数据类型。您可以指定每列的数据类型,用逗号分隔。通过指定数据类型,您可以覆盖爬网程序推断出的数据类型,并确保对数据进行适当分类。
可以在分类 SerDe 器CSV中设置要处理的,分类器将应用于数据目录。
创建自定义分类器时,您也可以将该分类器重复用于不同的爬网程序。
-
对于只有标题(无数据)的 csv 文件,这些文件将被归类为,UNKNOWN因为提供的信息不足。如果您在 CSV “列标题” 选项中指定 “有标题”,并提供了数据类型,我们可以正确地对这些文件进行分类。
您可以使用自定义CSV分类器来推断各种数据类型的CSV架构。您可以为分类器提供的自定义属性包括分隔符、CSV SerDe 选项、标题选项以及是否对数据执行某些验证。
Amazon Glue 中的自定义分类器值
定义CSV分类器时,需要向提供以下值Amazon Glue来创建分类器。此分类器的分类字段设置为 csv
。
- 分类器名称
-
分类器的名称。
- CSVSerde
-
设置要在 SerDe 分类器CSV中处理的,该分类器将应用于数据目录。选项包括 “打开” CSV SerDe、“Lazy Sim SerDe ple” 和 “无”。当您想让爬网程序执行检测时,可以指定“无”值。
- 列分隔符
-
一个自定义符号,表示分隔行中每个列条目的内容。提供一个 Unicode 字符。如果您无法键入分隔符,则可以将其复制并粘贴。这适用于可打印字符,包括您的系统不支持的字符(通常显示为 □)。
- 引用符号
-
一个自定义符号,表示将内容组合为单个列值的内容。必须与列分隔符不同。提供一个 Unicode 字符。如果您无法键入分隔符,则可以将其复制并粘贴。这适用于可打印字符,包括您的系统不支持的字符(通常显示为 □)。
- 列标题
-
表示应如何在CSV文件中检测列标题的行为。如果您的自定义CSV文件有列标题,请输入以逗号分隔的列标题列表。
- 处理选项:允许具有单列的文件
-
允许处理仅包含一列的文件。
- 处理选项:在标识列值之前去除空格
-
指定是否在标识列值类型之前去除值。
- 自定义数据类型 - 可选
-
输入用逗号分隔的自定义数据类型。指定文件中的自定义数据类型。CSV自定义数据类型必须为受支持的数据类型。支持的数据类型有:“BINARY”、“”、“BOOLEAN”、“”、“DATE”、“DECIMAL”、“”、“DOUBLE”、“FLOAT”、“INT”、“”、“LONG”、“SHORT”、“STRING”、“TIMESTAMP”。不受支持的数据类型将显示错误。