4

我有一个 df,在标有 url 的列中包含数千个链接,如下面的链接,针对不同的用户:

https://www.google.com/something
https://mail.google.com/anohtersomething
https://calendar.google.com/somethingelse
https://www.amazon.com/yetanotherthing

我有以下代码:

import urlparse

df['domain'] = ''
df['protocol'] = ''
df['domain'] = ''
df['path'] = ''
df['query'] = ''
df['fragment'] = ''
unique_urls = df.url.unique()
l = len(unique_urls)
i=0
for url in unique_urls:
    i+=1
    print "\r%d / %d" %(i, l),
    split = urlparse.urlsplit(url)
    row_index = df.url == url
    df.loc[row_index, 'protocol'] = split.scheme
    df.loc[row_index, 'domain'] = split.netloc
    df.loc[row_index, 'path'] = split.path
    df.loc[row_index, 'query'] = split.query
    df.loc[row_index, 'fragment'] = split.fragment

该代码能够正确解析和拆分网址,但速度很慢,因为我正在遍历 df 的每一行。有没有更有效的方法来解析 URL?

4

2 回答 2

5

您可以使用Series.map一行来完成相同的操作:

df['protocol'],df['domain'],df['path'],df['query'],df['fragment'] = zip(*df['url'].map(urlparse.urlsplit))

使用 timeit,当在 186 个 url 上运行时,它以2.31 ms每个循环而不是179 ms原始方法中的每个循环运行。(但是请注意,代码没有针对重复进行优化,并且将通过 urlparse 多次运行相同的 url。)

完整代码:

import pandas

urls = ['https://www.google.com/something','https://mail.google.com/anohtersomething','https://www.amazon.com/yetanotherthing'] # tested with list of 186 urls instead
df['protocol'],df['domain'],df['path'],df['query'],df['fragment'] = zip(*df['url'].map(urlparse.urlsplit))
于 2015-11-24T05:33:12.590 回答
0

我认为当您写回df. 看起来每个人都df.loc[row_index, ...]需要检查与 URL 总数一样多的行(大小为df.url)。这意味着首先您至少查看所有行一次以找到唯一的 url,然后为每个 url 再次查找匹配的行,然后为每次写入再次查找。因此,假设unique只进行一次完整扫描,那么您平均扫描表的1+N+(5N/2)时间。你真的应该只需要一次。

除非您有大量重复,否则您可以忽略重复项,df逐行遍历并确保每次迭代都使用整数索引。( .iloc) 如果您不在行中存储其他数据,您也可以一次分配所有字段:

df.iloc[idx] = {'protocol': ..., 'domain': ..., ...}
于 2015-11-24T04:56:02.710 回答