मुख्य सामग्री पर जाएँ

Python में वेब स्क्रैपिंग और NLP

वेब से उपन्यास स्क्रैप करना सीखें और शब्द आवृत्ति वितरण प्लॉट करें; आप Python पैकेज requests, BeautifulSoup और nltk के साथ अनुभव प्राप्त करेंगे।
· 14 मि॰ पढ़ें

AI के साथ खोजें

nltk Python

इस हफ्ते की शुरुआत में, मैंने एक Facebook Live Code along सत्र किया। इसमें, हमने कुछ बुनियादी नेचुरल लैंग्वेज प्रोसेसिंग का उपयोग करके उपन्यास Moby Dick में सबसे अधिक बार आने वाले शब्दों को प्लॉट किया। ऐसा करते हुए, हम प्रक्रिया पर निरंतर ध्यान रखते हुए निम्नलिखित डेटा साइंस पाइपलाइन में सोचने की प्रभावशीलता भी देखते हैं:

  1. अपना प्रश्न बताइए;
  2. अपना डेटा पाइए;
  3. अपने प्रश्न का उत्तर देने के लिए डेटा को सँभालिए/रैंगल कीजिए;
  4. अपने प्रश्न का उत्तर दीजिए;
  5. अपना समाधान इस तरह प्रस्तुत कीजिए कि अन्य लोग उसे समझ सकें।

इस पोस्ट में, आप सीखेंगे कि कैसे एक डेटा साइंस पाइपलाइन बनाकर Moby Dick सहित कई अन्य उपन्यासों में शब्दों के आवृत्ति वितरणों को प्लॉट किया जाए।

टिप: अगर आप Facebook Live फिर से देखना चाहें, तो नीचे दिया गया वीडियो देखें; आप 12वें मिनट पर स्किप कर सकते हैं, जहाँ Hugo आते हैं और सत्र वास्तव में शुरू होता है।

हम आपको उपन्यास नहीं देंगे: आप सीखेंगे कि Python पैकेज requests का उपयोग करके वेबसाइट Project Gutenberg (जिसमें मूल रूप से पुस्तकों का एक बड़ा कॉर्पस है) से उन्हें कैसे स्क्रैप किया जाए और BeautifulSoup का उपयोग करके इस वेब डेटा से उपन्यासों को कैसे निकाला जाए। फिर आप Natural Language ToolKit (nltk) का उपयोग करके उपन्यासों का विश्लेषण करेंगे। इस प्रक्रिया में, आप टोकनाइज़ेशन और स्टॉपवर्ड्स जैसे नेचुरल लैंग्वेज प्रोसेसिंग (NLP) के महत्वपूर्ण पहलुओं के बारे में सीखेंगे।

अंत में, आप Project Gutenberg पर मिलने वाले किसी भी उपन्यास के शब्द आवृत्ति वितरणों को विज़ुअलाइज़ करने में सक्षम होंगे। हालांकि, जो NLP कौशल आप विकसित करेंगे, वे उस अधिकतर डेटा पर भी लागू होंगे जिसका सामना डेटा वैज्ञानिक करते हैं, क्योंकि दुनिया के डेटा का बड़ा हिस्सा असंरचित होता है और उसमें बड़े पैमाने पर टेक्स्ट शामिल होता है।

उदाहरण के लिए, निम्नलिखित शब्द आवृत्ति वितरण किससे होगा?

word frequency distribution

यह पोस्ट एक Jupyter Notebook से जनरेट की गई है; आप इसे इस रिपॉज़िटरी में पा सकते हैं। यदि आपके कोई विचार, प्रतिक्रियाएँ और/या मनन हों, तो निःसंकोच मुझे Twitter पर संपर्क करें: @hugobowne.

पूर्व-चरण

अपने सिस्टम को सेट अप करने और तैयार करने के लिए README.md में दिए निर्देशों का पालन करें।

1. अपना प्रश्न बताइए

उपन्यास Moby Dick में सबसे अधिक बार आने वाले शब्द कौन से हैं और वे कितनी बार आते हैं?

2. अपना डेटा पाइए

आपका कच्चा डेटा Melville के उपन्यास Moby Dick का टेक्स्ट है। आप लगभग 800-पन्नों की इस पुस्तक का टेक्स्ट Python में कैसे लाएँगे?

खैर, इसे करने के कई तरीके हैं, लेकिन पहले यह समझें कि यह टेक्स्ट ऑनलाइन Project Gutenberg पर नि:शुल्क उपलब्ध है। वहाँ चलते हैं, Moby Dick खोजने की कोशिश करते हैं और फिर सम्बंधित URL को अपने Python नेमस्पेस में स्टोर करते हैं:

# Store url
url = 'https://www.gutenberg.org/files/2701/2701-h/2701-h.htm'

अब जब आपके पास URL है, तो आपको वेबसाइट का HTML फ़ेच करना होगा।

नोट कि HTML का अर्थ Hypertext Markup Language है और यह वेब के लिए मानक मार्कअप भाषा है।

आप इसे करने के लिए requests का उपयोग करने जा रहे हैं, जो वहाँ मौजूद सबसे लोकप्रिय और उपयोगी Python पैकेजों में से एक है। आप इसके बारे में और जान सकते हैं DataCamp के Importing Data in Python (Part 2) कोर्स में।

beautifulsoup Python

requests पैकेज की वेबसाइट के अनुसार:

Requests आपको बिना किसी मैनुअल मेहनत के, ऑर्गेनिक, घास-खिलाई गई HTTP/1.1 रिक्वेस्ट भेजने देता है।

और निम्नलिखित संगठन दावा करते हैं कि वे आंतरिक रूप से requests का उपयोग करते हैं:

Her Majesty's Government, Amazon, Google, Twilio, NPR, Obama for America, Twitter, Sony, और वे अमेरिकी संघीय संस्थान जो अपना नाम प्रकट नहीं करना पसंद करते हैं।

इसके अलावा,

Requests अब तक के सबसे अधिक डाउनलोड किए गए Python पैकेजों में से एक है, जो हर महीने 13,000,000 से अधिक डाउनलोड प्राप्त करता है। सभी कूल लोग यही कर रहे हैं!

आप वेबसाइट से एक GET रिक्वेस्ट करेंगे, जिसका मतलब है कि आप उससे डेटा ले रहे हैं। ब्राउज़र में कोई वेबपेज खोलते समय आप यही करते हैं। अन्य प्रकार की रिक्वेस्ट भी हैं, जैसे POST रिक्वेस्ट, लेकिन यहाँ हम उनकी परवाह नहीं करेंगे।

requests अपनी get फ़ंक्शन के साथ इसे आसान बनाता है। यहाँ रिक्वेस्ट करें और लौटे ऑब्जेक्ट के प्रकार की जाँच करें।

# Import `requests`
import requests

# Make the request and check object type
r = requests.get(url)
type(r)
requests.models.Response

यह एक Response ऑब्जेक्ट है। आप requests किकस्टार्ट गाइड में देख सकते हैं कि एक Response ऑब्जेक्ट में text नामक एट्रिब्यूट होता है, जो आपको उससे HTML प्राप्त करने देता है! आइए इसे करें और HTML प्रिंट करके देखें:

# Extract HTML from Response object and print
html = r.text
#print(html)

ठीक है! यह HTML बिल्कुल वैसा नहीं है जैसा आपको चाहिए। हालांकि, इसमें वह शामिल है जो आपको चाहिए: Moby Dick का टेक्स्ट। अब आपको इस HTML को रैंगल करके उपन्यास निकालना होगा।

3. प्रश्न का उत्तर देने के लिए डेटा रैंगल करें

भाग 1: HTML से टेक्स्ट प्राप्त करें

यहाँ आप BeautifulSoup पैकेज का उपयोग करेंगे। पैकेज वेबसाइट कहती है:

beautifulsoup package website

यह उम्मीद जगाता है!

सबसे पहले, पैकेज के नाम पर एक शब्द: Beautiful Soup? वेब डेवलपमेंट में, "tag soup" शब्द का उपयोग ऐसे HTML कोड के लिए किया जाता है जो संरचनात्मक या वाक्यविन्यास की दृष्टि से गलत हो। Beautiful Soup का सबसे अच्छा काम है टैग सूप को फिर से सुंदर बनाना और उससे आसानी से जानकारी निकालना! वास्तव में, इस पैकेज का उपयोग करते समय जो मुख्य ऑब्जेक्ट बनाया और क्वेरी किया जाता है, वह BeautifulSoup कहलाता है। सूप बनाने के बाद, हम उसके .get_text() मेथड का उपयोग टेक्स्ट निकालने के लिए कर सकते हैं।

# Import BeautifulSoup from bs4
from bs4 import BeautifulSoup


# Create a BeautifulSoup object from the HTML
soup = BeautifulSoup(html, "html5lib")
type(soup)
bs4.BeautifulSoup

इन सूप ऑब्जेक्ट्स से, आप जिस वेबसाइट को स्क्रैप कर रहे हैं उसके बारे में कई तरह की दिलचस्प जानकारी निकाल सकते हैं, जैसे शीर्षक:

# Get soup title
soup.title
<title>
      Moby Dick; Or the Whale, by Herman Melville
    </title>

या शीर्षक को एक स्ट्रिंग के रूप में:

# Get soup title as string
soup.title.string
'\n      Moby Dick; Or the Whale, by Herman Melville\n    '

या किसी पेज के < a > टैग्स (हाइपरलिंक्स) के भीतर पाए गए सभी URL:

# Get hyperlinks from soup and check out first several
soup.findAll('a')[:8]
[<a href="#link2H_4_0002"> ETYMOLOGY. </a>,
 <a href="#link2H_4_0003"> EXTRACTS (Supplied by a Sub-Sub-Librarian).
         </a>,
 <a href="#link2HCH0001"> CHAPTER 1. Loomings. </a>,
 <a href="#link2HCH0002"> CHAPTER 2. The Carpet-Bag. </a>,
 <a href="#link2HCH0003"> CHAPTER 3. The Spouter-Inn. </a>,
 <a href="#link2HCH0004"> CHAPTER 4. The Counterpane. </a>,
 <a href="#link2HCH0005"> CHAPTER 5. Breakfast. </a>,
 <a href="#link2HCH0006"> CHAPTER 6. The Street. </a>]

आप जो करना चाहते हैं वह है soup से टेक्स्ट निकालना, और इसके लिए एक बेहद मददगार .get_text() मेथड है।

टेक्स्ट प्राप्त करें, उसे प्रिंट करें और देखिए। क्या यह वही है जो आप चाहते हैं?

# Get the text out of the soup and print it
text = soup.get_text()
#print(text)

ध्यान दें कि यह अब लगभग वैसा है जैसा आप चाहते हैं।

यह उपन्यास का टेक्स्ट है जिसके शुरू में कुछ अवांछित सामग्री है और अंत में भी कुछ अवांछित सामग्री। यदि आप चाहें तो आप इसे हटा सकते हैं। हालांकि, यह सामग्री Moby Dick के टेक्स्ट की तुलना में बहुत कम है, इसलिए मोटे तौर पर, इसे छोड़ देना ठीक है और यहाँ हम यही तरीका अपनाएंगे। मज़बूत परिणामों के लिए, मैं इसे हटाने का सुझाव दूँगा।

अब जब आपके पास इच्छित टेक्स्ट है, तो यह गिनने का समय है कि प्रत्येक शब्द कितनी बार आता है और वह आवृत्ति हिस्टोग्राम प्लॉट करना है जो आप चाहते हैं: सहायता के लिए Natural Language Processing मौजूद है!

भाग 2: NLP के साथ अपने टेक्स्ट से शब्द निकालें

अब आप nltk, यानी Natural Language Toolkit, का उपयोग करेंगे

  1. टोकनाइज़ करने के लिए (टोकन, जैसे शब्द, में विभाजित करना);
  2. स्टॉपवर्ड्स हटाने के लिए (ऐसे शब्द जैसे 'a' और 'the' जो लगभग सभी अंग्रेज़ी टेक्स्ट में बहुत अधिक आते हैं)।

चरण 1: टोकनाइज़ करें

आप अपने टेक्स्ट को टोकनाइज़ करना चाहते हैं, यानी उसे शब्दों की सूची में विभाजित करना। मूलतः, आप टेक्स्ट के वे भाग अलग करना चाहते हैं जो व्हाइटस्पेस से अलग किए गए हैं।

इसके लिए, आप एक शक्तिशाली टूल का उपयोग करने जा रहे हैं जिसे रेगुलर एक्सप्रेशंस कहते हैं। एक रेगुलर एक्सप्रेशन, या संक्षेप में regex, अक्षरों का अनुक्रम होता है जो एक सर्च पैटर्न परिभाषित करता है। वे बदनाम रूप से उलझनभरे होते हैं और सबसे अच्छा उदाहरण से समझाए जाते हैं।

  • आपके पास स्ट्रिंग 'peter piper picked a peck of pickled peppers' है और आप इसमें से उन सभी शब्दों की सूची निकालना चाहते हैं जो 'p' से शुरू होते हैं।

वह रेगुलर एक्सप्रेशन जो 'p' से शुरू होने वाले सभी शब्दों से मेल खाता है, 'p\w+' है। इसे समझते हैं:

  • रेगुलर एक्सप्रेशन की शुरुआत का 'p' मतलब है कि आप केवल उन अक्षर अनुक्रमों से मेल कराएँगे जो 'p' से शुरू होते हैं;
  • '\w' एक विशेष करैक्टर है जो किसी भी अल्फ़ान्यूमेरिक A-z, a-z, 0-9, साथ ही अंडरस्कोर से मेल खाएगा;
  • '+' बताता है कि regex में पिछला करैक्टर जितनी बार भी चाहे, उन स्ट्रिंग्स में आ सकता है जिनसे आप मेल कराने की कोशिश कर रहे हैं। इसका मतलब '\w+' मनमाने लंबाई के अल्फ़ान्यूमेरिक करैक्टर्स और अंडरस्कोर के अनुक्रमों से मेल खाएगा।

इन्हें जोड़कर देखें तो रेगुलर एक्सप्रेशन 'p\w+' उन सभी उपस्ट्रिंग्स से मेल खाएगा जो 'p' से शुरू होती हैं और उनके बाद अल्फ़ान्यूमेरिक करैक्टर्स और अंडरस्कोर आते हैं। अधिकांश सार्थक अंग्रेज़ी टेक्स्ट में यह 'p' से शुरू होने वाले शब्दों के अनुरूप होगा।

अब आप बिल्ट-इन Python पैकेज re का उपयोग करके 'peter piper picked a peck of pickled peppers' वाक्य से 'p' से शुरू होने वाले सभी शब्दों को एक वार्म-अप के रूप में निकालेंगे।

# Import regex package
import re

# Define sentence
sentence = 'peter piper pick a peck of pickled peppers'

# Define regex
ps = 'p\w+'


# Find all words in sentence that match the regex and print them
re.findall(ps, sentence)
['peter', 'piper', 'pick', 'peck', 'pickled', 'peppers']

यह काफी अच्छा दिखता है। अब, यदि 'p\w+' वह regex है जो 'p' से शुरू होने वाले शब्दों से मेल खाता है, तो वह regex क्या होगा जो सभी शब्दों से मेल खाता है?

अब यह आपका काम है कि ऊपर दिए हमारे छोटे Peter Piper वाक्य के लिए ऐसा करें।

# Find all words and print them
re.findall('\w+', sentence)
['peter', 'piper', 'pick', 'a', 'peck', 'of', 'pickled', 'peppers']

अब आप यही काम text के साथ कर सकते हैं, वह स्ट्रिंग जिसमें Moby Dick है:

# Find all words in Moby Dick and print several
tokens = re.findall('\w+', text)
tokens[:8]
['Moby', 'Dick', 'Or', 'the', 'Whale', 'by', 'Herman', 'Melville']

ध्यान दें कि यह Natural Language Toolkit nltk से भी किया जा सकता है:

# Import RegexpTokenizer from nltk.tokenize
from nltk.tokenize import RegexpTokenizer

# Create tokenizer
tokenizer = RegexpTokenizer('\w+')



# Create tokens
tokens = tokenizer.tokenize(text)
tokens[:8]
['Moby', 'Dick', 'Or', 'the', 'Whale', 'by', 'Herman', 'Melville']

ठीक है! आप लगभग पहुँच गए हैं। लेकिन ध्यान दें कि ऊपर 'Or' में बड़ा 'O' है और अन्य जगहों पर ऐसा न भी हो, फिर भी 'Or' और 'or' को आप एक ही शब्द मानना चाहेंगे। इस कारण, आपको Moby Dick के सभी शब्दों की ऐसी सूची बनानी होगी जिसमें सभी बड़े अक्षरों को छोटे अक्षरों में बदल दिया गया हो। आपको स्ट्रिंग मेथड .lower() काम आएगा:

# Initialize new list
words = []


# Loop through list tokens and make lower case
for word in tokens:
    words.append(word.lower())


# Print several items from list as sanity check
words[:8]
['moby', 'dick', 'or', 'the', 'whale', 'by', 'herman', 'melville']

चरण 2: स्टॉप वर्ड्स हटाएँ

अंग्रेज़ी भाषा में बहुत अधिक आने वाले 'the', 'of' और 'a' जैसे शब्दों (जिन्हें स्टॉपवर्ड्स कहा जाता है) को हटाना सामान्य अभ्यास है क्योंकि वे इतने रोचक नहीं होते। इन सभी तकनीकों पर अधिक जानकारी के लिए हमारा Natural Language Processing Fundamentals in Python कोर्स देखें।

nltk पैकेज में अंग्रेज़ी के स्टॉपवर्ड्स की सूची है जिसे आप अब sw के रूप में स्टोर करेंगे और जिसके शुरुआती कुछ तत्व प्रिंट करेंगे।

यदि यहाँ आपको कोई त्रुटि मिले, तो अपने सिस्टम पर स्टॉपवर्ड्स इंस्टॉल करने के लिए कमांड nltk.download('stopwords') चलाएँ।

# Import nltk
import nltk

# Get English stopwords and print some of them
sw = nltk.corpus.stopwords.words('english')
sw[:5]
['i', 'me', 'my', 'myself', 'we']

आपको words में मौजूद उन सभी शब्दों की सूची चाहिए जो sw में नहीं हैं। इसे पाने का एक तरीका यह है कि words के सभी तत्वों पर लूप चलाएँ और यदि वे sw में न हों तो उन्हें एक नई सूची में जोड़ दें:

# Initialize new list
words_ns = []

# Add to words_ns all words that are in words but not in sw
for word in words:
    if word not in sw:
        words_ns.append(word)

# Print several list items as sanity check
words_ns[:5]
['moby', 'dick', 'whale', 'herman', 'melville']

4. अपने प्रश्न का उत्तर दें

हमारा प्रश्न था 'उपन्यास Moby Dick में सबसे अधिक बार आने वाले शब्द कौन से हैं और वे कितनी बार आते हैं?'

अब आप nltk का उपयोग करके केवल दो लाइनों में Moby Dick के शब्दों का एक आवृत्ति हिस्टोग्राम प्लॉट कर सकते हैं। इसके लिए,

  • आप फ़ंक्शन nltk.FreqDist() का उपयोग करके एक फ़्रीक्वेंसी डिस्ट्रीब्यूशन ऑब्जेक्ट बनाएँ;
  • बने हुए ऑब्जेक्ट की plot() मेथड का उपयोग करें।
#Import datavis libraries
import matplotlib.pyplot as plt
import seaborn as sns

# Figures inline and set visualization style
%matplotlib inline
sns.set()

# Create freq dist and plot
freqdist1 = nltk.FreqDist(words_ns)
freqdist1.plot(25)

NLP pipeline Python

5. अपना समाधान प्रस्तुत करें

रोचक बात यह है कि, अपने प्रश्न का उत्तर देने के लिए nltk का उपयोग करते हुए, हम वास्तव में अपना समाधान पहले ही ऐसी शैली में प्रस्तुत कर चुके हैं जिसे दूसरों तक संप्रेषित किया जा सके: एक आवृत्ति वितरण प्लॉट! आप सबसे सामान्य शब्दों और उनकी आवृत्ति पढ़ सकते हैं। उदाहरण के लिए, 'whale' उपन्यास का सबसे आम शब्द है (स्वाभाविक है), स्टॉपवर्ड्स को छोड़कर, और यह 1200 से अधिक बार आता है!

अतिरिक्त सामग्री

चूँकि आपने देखा कि Project Gutenberg पर बहुत सारे उपन्यास हैं, जिनके लिए हम ये शब्द आवृत्ति हिस्टोग्राम बना सकते हैं, तो यह समझ में आता है कि आप अपना एक फ़ंक्शन लिखें जो यह सब कर दे:

 def plot_word_freq(url):
    """Takes a url (from Project Gutenberg) and plots a word frequency
    distribution"""
    # Make the request and check object type
    r = requests.get(url)
    # Extract HTML from Response object and print
    html = r.text
    # Create a BeautifulSoup object from the HTML
    soup = BeautifulSoup(html, "html5lib")
    # Get the text out of the soup and print it
    text = soup.get_text()
    # Create tokenizer
    tokenizer = RegexpTokenizer('\w+')
    # Create tokens
    tokens = tokenizer.tokenize(text)
    # Initialize new list
    words = []
    # Loop through list tokens and make lower case
    for word in tokens:
        words.append(word.lower())
    # Get English stopwords and print some of them
    sw = nltk.corpus.stopwords.words('english')
    # Initialize new list
    words_ns = []
    # Add to words_ns all words that are in words but not in sw
    for word in words:
        if word not in sw:
            words_ns.append(word)
    # Create freq dist and plot
    freqdist1 = nltk.FreqDist(words_ns)
    freqdist1.plot(25)

अब इस फ़ंक्शन का उपयोग करके Project Gutenberg के अन्य टेक्स्ट से शब्द आवृत्ति वितरण प्लॉट करें:

  • Pride and Prejudice:
plot_word_freq('https://www.gutenberg.org/files/42671/42671-h/42671-h.htm')

web scraping Python

  • Robinson Crusoe
plot_word_freq('https://www.gutenberg.org/files/521/521-h/521-h.htm')

word distribution tokenize

  • The King James Bible
plot_word_freq('https://www.gutenberg.org/files/10/10-h/10-h.htm')

word frequency

निष्कर्ष

इस पोस्ट में, आपने Moby Dick सहित कई अन्य उपन्यासों में शब्दों के आवृत्ति वितरणों को प्लॉट करने के लिए एक डेटा साइंस पाइपलाइन बनाना सीखा। आपने Python पैकेज requests का उपयोग करके वेबसाइट Project Gutenberg (पुस्तकों का बड़ा कॉर्पस) से उन्हें स्क्रैप करना और BeautifulSoup का उपयोग करके इस वेब डेटा से उपन्यासों को निकालना सीखा। फिर आपने Natural Language ToolKit (nltk) का उपयोग करके उपन्यासों का विश्लेषण किया। इस प्रक्रिया में आपने नेचुरल लैंग्वेज प्रोसेसिंग (NLP) के महत्वपूर्ण पहलुओं जैसे टोकनाइज़ेशन और स्टॉपवर्ड्स के बारे में सीखा। अब आप Project Gutenberg पर मिलने वाले किसी भी उपन्यास के शब्द आवृत्ति वितरणों को विज़ुअलाइज़ कर सकते हैं। आपके द्वारा विकसित किए गए NLP कौशल उस अधिकतर डेटा पर भी लागू होते हैं जिसका सामना डेटा वैज्ञानिक करते हैं, क्योंकि दुनिया के डेटा का बड़ा हिस्सा असंरचित होता है और उसमें बहुत सारा टेक्स्ट शामिल होता है।

यह पोस्ट एक Jupyter Notebook से जनरेट की गई है; आप इसे इस रिपॉज़िटरी में पा सकते हैं। यदि आपके कोई विचार, प्रतिक्रियाएँ और/या मनन हों, तो निःसंकोच मुझे ट्विटर पर संपर्क करें: @hugobowne. बताएँ कि आप कौन से रोचक प्रोजेक्ट बनाते हैं।

DataCamp के Web Scraping using Python (and Beautiful Soup) और How to Use Python to Scrape Amazon ट्यूटोरियल देखें।

विषय