рассмотрим этот простой пример
df = pd.DataFrame({'link' : ['https://en.wikipedia.org/wiki/World%27s_funniest_joke',
'https://en.wikipedia.org/wiki/The_Funniest_Joke_in_the_World']})
df
Out[169]:
link
0 https://en.wikipedia.org/wiki/World%27s_funniest_joke
1 https://en.wikipedia.org/wiki/The_Funniest_Joke_in_the_World
Я хочу проанализировать каждую ссылку с помощью beautiful soup
и сохранить проанализированный контент в другой столбец моего фрейма данных. Следующее, кажется, работает хорошо:
def puller(mylink):
doc = requests.get(mylink)
return BeautifulSoup(doc.content, 'html5lib')
df['parsed'] = df.apply(lambda x: puller(x))
df['mytag'] = df.parsed.apply(lambda x: x.find_all('p'))
Проблема в том, что я получаю списки, и мне нужно работать с текстом внутри них. В частности, я пытаюсь оставить в тексте только те абзацы, в которых упоминается joke
, но у меня не получается.
def extractor(mylist):
return list(filter(lambda x: re.search('joke', x), mylist))
df.mytag.apply(lambda x: extractor(x))
TypeError: expected string or bytes-like object
Как лучше поступить здесь?
Спасибо!
добавил еще немного информации. Спасибо
упростил и прояснил вопрос
Каждая запись df[mytag]
представляет собой список элементов BeautifulSoup '<p>'
. Вы можете написать функцию, которая берет этот список и возвращает текст, содержащий ваше слово. Затем используйте .apply
поверх df[mytag]
, чтобы он работал во всех ваших строках.
def myfunc(list_of_ps, word='joke'):
'''
This will return a list of string text paragraphs
containing the word.
'''
result_ps = []
for p in list of ps:
if word in p.text:
result_ps.append(p.text) # p if p itself is needed
return result_ps if result_ps else None
df['mytag'].apply(myfunc)
Обновлено:
Ошибка в вашем вопросе отражает факт, выделенный курсивом выше. re.search ожидает строки в качестве параметров. Другими словами, x
в этом вызове функции должен быть строкой или байтовым объектом. В данном случае это объект BeautifulSoup как отдельный элемент <p>
. Ошибку можно устранить, получив строковый текст элемента в виде x.text
.
Pandas API предназначен для использования с более примитивными типами данных; вам лучше написать функции, которые преобразуют ссылку -> текст, который вы хотите, а затем вызывать apply
. Вот одно из решений:
import pandas as pd
from bs4 import BeautifulSoup
df = pd.DataFrame({'link' : [
'https://en.wikipedia.org/wiki/World%27s_funniest_joke',
'https://en.wikipedia.org/wiki/The_Funniest_Joke_in_the_World'
]
})
def parse_link(mylink):
doc = requests.get(mylink)
return BeautifulSoup(doc.content, 'html5lib')
def matching_paragraphs(soup, text):
res = [p.get_text() for p in soup.find_all("p") if text in p.get_text()]
return res
def apply_func(link, text):
soup = parse_link(link)
res = matching_paragraphs(soup, text=text)
return res
df['text'] = df.link.apply(apply_func, args=("joke",))
выход:
link text
0 https://en.wikipedia.org/wiki/World%27s_funnie... [The "world's funniest joke" is a term used by...
1 https://en.wikipedia.org/wiki/The_Funniest_Jok... ["The Funniest Joke in the World" (also "Joke ...
Более разумно с помощью фрейма данных вы можете преобразовать список строк в строки:
df.explode(column = "text", ignore_index=True)
результат:
link text
0 https://en.wikipedia.org/wiki/World%27s_funnie... The "world's funniest joke" is a term used by ...
1 https://en.wikipedia.org/wiki/World%27s_funnie... The winning joke, which was later found to be ...
2 https://en.wikipedia.org/wiki/World%27s_funnie... Researchers also included five computer-genera...
3 https://en.wikipedia.org/wiki/The_Funniest_Jok... "The Funniest Joke in the World" (also "Joke W...
4 https://en.wikipedia.org/wiki/The_Funniest_Jok... The sketch appeared in the first episode of th...
5 https://en.wikipedia.org/wiki/The_Funniest_Jok... The sketch is framed in a documentary style an...
6 https://en.wikipedia.org/wiki/The_Funniest_Jok... The British Army are soon eager to determine "...
7 https://en.wikipedia.org/wiki/The_Funniest_Jok... The German version is described as being "over...
8 https://en.wikipedia.org/wiki/The_Funniest_Jok... The Germans attempt counter-jokes, but each at...
9 https://en.wikipedia.org/wiki/The_Funniest_Jok... The British joke is said to have been laid to ...
10 https://en.wikipedia.org/wiki/The_Funniest_Jok... The footage of Adolf Hitler is taken from Leni...
11 https://en.wikipedia.org/wiki/The_Funniest_Jok... If the German version of the joke is entered i...
Это, вероятно, не правильный вариант использования для взрыва. Кроме того, вы должны объяснить природу
df['mytag']
на примерах.