Фильтровать только ссылки в кадре данных на основе определенного имени домена - PullRequest
0 голосов
/ 30 сентября 2019

У меня есть пандас с 5 колонками. Мне нужно отфильтровать кадр данных по столбцу link на основе доменного имени в списке и посчитать количество строк для каждого процесса несколько раз. Предположим, у меня есть следующий фрейм данных:

url_id | link
------------------------------------------------------------------------
1      | http://www.example.com/somepath
2      | http://www.somelink.net/example
3      | http://other.someotherurls.ac.uk/thisissomelink.net&part/sample 
4      | http://part.example.com/directory/files  

Я хочу отфильтровать фрейм данных на основе доменного имени из списка ниже и подсчитать количество каждого результата:

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']

Ниже приводитсяожидаемый результат:

domain       | no_of_links
--------------------------
example.com  |  2
other.com    |  0
somelink.net |  1
sample.com   |  0

Это мой код:

from tld import get_tld 
import pandas as pd

def urlparsing(row):
    url = row['link']
    res = get_tld(url,as_object=True)
    return (res.fld)

link = ({"url_id":[1,2,3,4],"link":["http://www.example.com/somepath",
            "http://www.somelink.net/example",
            "http://other.someotherurls.ac.uk/thisissomelink.net&part/sample",
            "http://part.example.com/directory/files"]})

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
df_link = pd.DataFrame(link)

ref_dom = []
for dom in domains:   
    ddd = df_link[(df_link.apply(lambda row: urlparsing(row), axis=1)).str.contains(dom, regex=False)]     
    ref_dom.append([dom, len(ddd)])

pd.DataFrame(ref_dom, columns=['domain','no_of_links'])

В основном мой код работает. Однако, когда размер фрейма данных очень велик (более 5 миллионов строк), а список доменных имен составляет более ста тысяч, этот процесс занимает мое время. Если у вас есть альтернативный способ сделать это быстрее, пожалуйста, дайте мне знать. Любая помощь будет оценена. Спасибо.

1 Ответ

0 голосов
/ 30 сентября 2019

вы можете сделать это с помощью регулярных выражений и функции findall функции df.str

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
pat = "|".join([f"http[s]?://(?:\w*\.)?({domain})" 
                 for domain in map(lambda x: x.replace(".","\."), domains)])
match = df["link"].str.findall(pat).explode().explode()
match = match[match.str.len()>0]
match.groupby(match).count()

результат

link
example.com     2
somelink.net    1
Name: link, dtype: int64

Для панд до 0,25

domains = ['example.com', 'other.com', 'somelink.net' , 'sample.com']
pat = "|".join([f"http[s]?://(?:\w*\.)?({domain})" 
                 for domain in map(lambda x: x.replace(".","\."), domains)])

match = df["link"].str.findall(pat) \
.apply(lambda x: "".join([domain for match in x for domain in match]).strip())

match = match[match.str.len()>0]
match.groupby(match).count()

для получения доменов с 0 ссылками, также вы можете объединить результат с df, имеющим весь домен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...