BigQuery / DataPrep:提取字数的有效方法;将 HTML 转换为纯文本
Posted
技术标签:
【中文标题】BigQuery / DataPrep:提取字数的有效方法;将 HTML 转换为纯文本【英文标题】:BigQuery / DataPrep: Efficient way to extract word counts; to convert HTML to plaintext 【发布时间】:2017-10-09 11:06:46 【问题描述】:我有一个存储在 BigQuery 中的约 470 万个文档的表。有些是纯文本,有些是 html。它们大约有 2k 个令牌,变化很大。我主要使用 DataPrep 进行处理。
我想提取这些标记并计算 TF-IDF 值。
令牌计数
其中一个更耗时的步骤是:
id, document
1, "foo bar foo baz"
2, "foo bar bar qux"
然后把它变成这样:
id, word, count
1, foo, 2
1, bar, 1
1, baz, 1
2, foo, 1
2, bar, 2
2, qux, 1
一种方法是这样的:
alphanum-underscore+
的文档摘录列表
id, wordlist
1, ["foo", "bar", "foo", "baz"]
2, ["foo", "bar", "bar", "qux"]
扁平化词表
id, word
1, foo
1, bar
1, foo
1, baz
2, foo
2, bar
2, bar
2, qux
按组聚合:id、word、值:count()
id, word, count
1, foo, 2
1, bar, 1
1, baz, 1
2, foo, 1
2, bar, 2
2, qux, 1
但是,第 2 步和第 3 步非常慢,尤其是对于大型文档。
理想情况下,我应该能够拥有一个将["foo", "bar", "foo", "baz"]
转换为"foo":2, "bar":1, "baz":1
的函数。这不需要 flatten-then-group 操作来提取计数,并且随后的 flatten 会更小(因为它在唯一的术语而不是每个术语上运行)。
但是,我还没有想出在 DataPrep 中执行此操作的任何方法。 :-/
有什么更有效的方法来做到这一点?
HTML 转纯文本
我的源数据是纯文本和 html 的组合。在 370 万份文档中,只有大约 80 万份有明文可用。
我想以某种合理的方式将 html 转换为纯文本(例如,相当于 Nokogiri #content),这样我就可以对结果进行令牌提取。
我可以启动一个执行 bq query
的集群,摄取 html,使用 nokogiri 处理它,然后将其输出到处理过的表中。但这有点复杂,需要大量的 i/o。
有没有更简单/更有效的方法来做到这一点?
【问题讨论】:
【参考方案1】:我认为您可以在 BigQuery 中完成所有操作 下面应该给你一个好的开始 在每个文档和整个语料库中都有词频 并且 html 以及只是数字的单词都被删除了 您现在可以在此处添加任何额外的处理,包括 TF-IDF
#standardSQL
WITH removed_html AS (
SELECT id, REGEXP_REPLACE(document, r'<[^>]*>', ' ') AS document
FROM `yourTable`
),
words_in_documents AS (
SELECT id,
ARRAY(
SELECT AS STRUCT word, COUNT(1) AS cnt
FROM UNNEST(REGEXP_EXTRACT_ALL(document, r'[\w_]+')) AS word
GROUP BY word
HAVING NOT REGEXP_CONTAINS(word, r'^\d+$')
) AS words
FROM removed_html
),
words_in_corpus AS (
SELECT word, SUM(cnt) AS cnt
FROM words_in_documents, UNNEST(words) AS words
GROUP BY word
)
SELECT *
FROM words_in_corpus
您可以使用问题中的虚拟数据来测试/玩这个
#standardSQL
WITH `yourTable` AS (
SELECT 1 AS id, "foo bar, foo baz" AS document UNION ALL
SELECT 2, "foo bar bar qux" UNION ALL
SELECT 3, '''
<h5 id="last_value">LAST_VALUE</h5>
<pre class="codehilite"><code>LAST_VALUE (value_expression [RESPECT | IGNORE NULLS])</code></pre>
'''
),
removed_html AS (
SELECT id, REGEXP_REPLACE(document, r'<[^>]*>', ' ') AS document
FROM `yourTable`
),
words_in_documents AS (
SELECT id,
ARRAY(
SELECT AS STRUCT word, COUNT(1) AS cnt
FROM UNNEST(REGEXP_EXTRACT_ALL(document, r'[\w_]+')) AS word
GROUP BY word
HAVING NOT REGEXP_CONTAINS(word, r'^\d+$')
) AS words
FROM removed_html
),
words_in_corpus AS (
SELECT word, SUM(cnt) AS cnt
FROM words_in_documents, UNNEST(words) AS words
GROUP BY word
)
SELECT *
FROM words_in_corpus
ORDER BY cnt DESC
【讨论】:
以上是关于BigQuery / DataPrep:提取字数的有效方法;将 HTML 转换为纯文本的主要内容,如果未能解决你的问题,请参考以下文章