Скажем, у меня есть столбец, заполненный URL-адресами, как показано ниже:
+------------------------------------------+
|url |
+------------------------------------------+
|https://www.example1.com?param1=1¶m2=a|
|https://www.example2.com?param1=2¶m2=b|
|https://www.example3.com?param1=3¶m2=c|
+------------------------------------------+
Каков наилучший способ извлечения параметров URL-адресов из этого столбца и добавления их в виде столбцов к фрейму данных для создания ниже?
+-------------------------------------------+---------------+
| url| param1| param2|
+-------------------------------------------+---------------+
|https://www.example1.com?param1=1¶m2=a | 1| a|
|https://www.example2.com?param1=2¶m2=b | 2| b|
|https://www.example3.com?param1=3¶m2=c | 3| c|
|etc... | etc...| etc...|
+-------------------------------------------+---------------+
Мои попытки
Я могу придумать два возможных способа сделать это, используя functions.regexp_extract
из библиотеки pyspark или urllib.parse.parse_qs
и urllib.parse.urlparse
из стандартная библиотека. В первом решении используется регулярное выражение, которое является хитрым методом извлечения параметров из строк, но последнее должно быть заключено в используемую UDF.
from pyspark.sql import *
from pyspark.sql import functions as fn
df = spark.createDataFrame(
[
("https://www.example.com?param1=1¶m2=a",),
("https://www.example2.com?param1=2¶m2=b",),
("https://www.example3.com?param1=3¶m2=c",)
],
["url"]
)
Решение Regex:
df2 = df.withColumn("param1", fn.regexp_extract('url', 'param1=(\d)', 1))
df2 = df2.withColumn("param2", fn.regexp_extract('url', 'param2=([a-z])', 1))
df2.show()
>> +------------------------------------------+------+------+
>> |url |param1|param2|
>> +------------------------------------------+------+------+
>> |https://www.example1.com?param1=1¶m2=a|1 |a |
>> |https://www.example2.com?param1=2¶m2=b|2 |b |
>> |https://www.example3.com?param1=3¶m2=c|3 |c |
>> +------------------------------------------+------+------+
Решение UDF:
from urllib.parse import urlparse, parse_qs
from pyspark.sql.types import MapType, StringType
extract_params = udf(lambda x: {k: v[0] for k, v in parse_qs(urlparse(x).query).items()}, MapType(StringType(), StringType()))
df3 = df.withColumn(
"params", extract_params(df.url)
)
df3.withColumn(
"param1", df3.params['param1']
).withColumn(
"param2", df3.params['param2']
).drop("params").show()
>> +------------------------------------------+------+------+
>> |url |param1|param2|
>> +------------------------------------------+------+------+
>> |https://www.example1.com?param1=1¶m2=a|1 |a |
>> |https://www.example2.com?param1=2¶m2=b|2 |b |
>> |https://www.example3.com?param1=3¶m2=c|3 |c |
>> +------------------------------------------+------+------+
Я хотел бы использовать универсальность библиотеки, подобной urllib
, но также хотел бы оптимизировать ее написание в функциях pyspark. Есть ли лучший способ, чем два, которые я пробовал до сих пор?