इस सरल उदाहरण पर विचार करें

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

यहां आगे बढ़ने का सबसे अच्छा तरीका क्या है?

धन्यवाद!

1
ℕʘʘḆḽḘ 15 पद 2020, 07:01

2 जवाब

सबसे बढ़िया उत्तर

पांडा एपीआई को अधिक आदिम डेटाटाइप पर उपयोग करने के लिए डिज़ाइन किया गया है; आपके लिए बेहतर होगा कि आप ऐसे फंक्शन्स लिखें जो लिंक को कनवर्ट करते हैं -> टेक्स्ट जो आप चाहते हैं और फिर 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...
2
anon01 15 पद 2020, 19:37

df[mytag] की प्रत्येक प्रविष्टि सुंदर सूप '<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 उस फ़ंक्शन कॉल में एक स्ट्रिंग या बाइट जैसी वस्तु होनी चाहिए। इस मामले में, यह एक व्यक्तिगत <p> तत्व के रूप में एक सुंदर सूप वस्तु है। तत्व के स्ट्रिंग टेक्स्ट को x.text के रूप में प्राप्त करके त्रुटि का समाधान किया जा सकता है।

1
skuzzy 15 पद 2020, 08:09