Python और BeautifulSoup 4 के साथ Reddit स्क्रैपिंग
इस ट्यूटोरियल में, आप requests का उपयोग करके वेब पेज प्राप्त करना, ब्राउज़र में वेब पेजों का विश्लेषण करना, और BeautifulSoup के साथ कच्चे HTML से जानकारी निकालना सीखेंगे।
हम जो स्क्रिप्ट लिखेंगे उसका तैयार, कार्यरत उदाहरण आपको यहाँ मिल जाएगा।
वेब स्क्रैपिंग क्या है?
ठीक है, तो आखिर वेब स्क्रैपिंग है क्या? नाम से ही स्पष्ट है—यह वेबपेजों से डेटा ‘स्क्रैप’ या निकालने की एक विधि है। आपके ब्राउज़र में इंटरनेट पर जो कुछ भी दिखता है, इस ट्यूटोरियल सहित, उसे आप अपने स्थानीय हार्ड ड्राइव पर स्क्रैप कर सकते हैं।
वेब स्क्रैपिंग के कई उपयोग हैं। किसी भी डेटा विश्लेषण में पहला कदम डेटा प्राप्त करना होता है। इंटरनेट मानव इतिहास और ज्ञान का एक विशाल भंडार है, और आपके पास जो भी जानकारी चाहिए उसे निकालने और उसका इच्छानुसार उपयोग करने के साधन हैं।
अपने ट्यूटोरियल में, हम Python और BeautifulSoup 4 पैकेज का उपयोग करके किसी सबरेडिट से जानकारी लेंगे। हमारा लक्ष्य datascience सबरेडिट है। हम इस सबरेडिट पर पहली 1000 पोस्ट्स लेना चाहते हैं और उन्हें CSV फ़ाइल में निर्यात करना चाहते हैं। हम जानना चाहते हैं कि इसे किसने पोस्ट किया, साथ ही इसे कितने लाइक और कमेंट मिले।
इस ट्यूटोरियल में हम क्या कवर करेंगे:
requests का उपयोग करके वेब पेज प्राप्त करना
जानकारी के लिए ब्राउज़र में वेब पेजों का विश्लेषण
BeautifulSoup के साथ कच्चे HTML से जानकारी निकालना
नोट: हम Reddit की पुरानी साइट का उपयोग करेंगे क्योंकि वह लोड होने में हल्की है, और इस प्रकार आपकी मशीन पर कम भार डालती है।
पूर्वापेक्षाएँ
यह ट्यूटोरियल मानकर चलता है कि आप निम्न बातों से परिचित हैं:
अपने कंप्यूटर पर Python स्क्रिप्ट्स चलाना
HTML संरचना का बुनियादी ज्ञान
आप उपर्युक्त कौशल DataCamp के Python शुरुआती कोर्स में सीख सकते हैं। यह कहते हुए, यहाँ उपयोग की गई संकल्पनाएँ बहुत न्यूनतम हैं, और बहुत कम Python ज्ञान के साथ भी आप काम चला सकते हैं।
अब जब यह हो गया, तो हम अपने वेब स्क्रैपर बनाने के पहले हिस्से पर बढ़ सकते हैं। वास्तव में, किसी भी Python स्क्रिप्ट का पहला हिस्सा: imports।
अपने स्क्रैपर में, हम निम्न पैकेजों का उपयोग करेंगे:
requests
beautifulsoup4
आप इन पैकेजों को pip से, इस तरह इंस्टॉल कर सकते हैं:
पैकेज डाउनलोड करने के बाद, उन्हें अपने कोड में import कर लें।
import requests
import csv
import time
from bs4 import BeautifulSoup4
संचालित द्वारा
हम अपने परिणामों को CSV फ़ाइल में लिखने के लिए Python के बिल्ट-इन csv मॉड्यूल का उपयोग करेंगे। आपने ऊपर दिए स्निपेट में एक अजीब सी बात देखी होगी। यानी, हमने beautifulsoup4 नाम का पैकेज डाउनलोड किया, लेकिन bs4 नाम के मॉड्यूल से import किया। यह Python में वैध है, और यद्यपि आमतौर पर इसे अच्छा नहीं माना जाता, यह किसी नियम के विरुद्ध नहीं है।
प्लेटफ़ॉर्म नीतियों पर महत्वपूर्ण नोट
अगले चरणों में बताई गई स्क्रैपिंग तकनीकों का उपयोग करने से पहले, Reddit या किसी अन्य वेबसाइट जिसकी आप स्क्रैपिंग करना चाहते हैं, की वर्तमान सेवा शर्तें अवश्य जाँचें। वेबसाइट नीतियाँ समय के साथ बदल सकती हैं। सितंबर 2024 का Reddit User Agreement पूर्व लिखित सहमति के बिना स्क्रैपिंग पर रोक लगाता है (धारा 7 देखें)। आगे बढ़ने से पहले हमेशा सुनिश्चित करें कि आप साइट के नवीनतम उपयोग दिशानिर्देशों का पालन कर रहे हैं।
Reddit को क्रॉल करने के पहले कदम
तो हमारा पर्यावरण सेटअप हो चुका है। अब हमें उस वेबपेज का URL चाहिए जिसे हम स्क्रैप करना चाहते हैं। अपने ट्यूटोरियल के लिए, हम Reddit के ‘datascience’ सबरेडिट का उपयोग कर रहे हैं। स्क्रिप्ट लिखना शुरू करने से पहले, थोड़ा फील्डवर्क करना होगा। एक वेब ब्राउज़र खोलें, और संबंधित सबरेडिट पर जाएँ।
ध्यान दें कि हम अपने स्क्रैपर के लिए सबरेडिट के पुराने संस्करण का उपयोग करेंगे। नए संस्करण में कुछ महत्त्वपूर्ण जानकारी वेबपेज के अंदरूनी हिस्से में छिपी रहती है। नई साइट से भी यह जानकारी निकाली जा सकती है, लेकिन सरलता के लिए, हम पुराने संस्करण का उपयोग करेंगे जिसमें सब कुछ साफ़-साफ़ दिखता है।
लिंक खोलते ही आपको जानकारी का सैलाब दिखेगा। इसमें से हमें क्या चाहिए? सभी लिंक्स को जाँचना शुरू करें, तो पता चलेगा कि Reddit पोस्ट्स दो प्रकार की होती हैं:
इनबाउंड
आउटबाउंड
इनबाउंड लिंक वे होते हैं जो Reddit के भीतर की सामग्री की ओर इशारा करते हैं, और आउटबाउंड इसके उलट। यह इसलिए महत्त्वपूर्ण है क्योंकि हमें केवल इनबाउंड लिंक चाहिए। यानी वे पोस्ट्स जिनमें उपयोगकर्ताओं द्वारा लिखा गया टेक्स्ट हो, न कि केवल अन्य वेबसाइटों के लिंक।
तो हमें पता है कि क्या चाहिए, अब इसे निकालें कैसे? यदि आप पोस्ट्स के शीर्षक देखते हैं, तो उनके बाद ब्रैकेट में कुछ टेक्स्ट आता है। जिन पोस्ट्स में हमारी दिलचस्पी है, उनके बाद ‘(self.datascience)’ आता है। तर्कसंगत रूप से, माना जा सकता है कि ‘self’ Reddit की रूट डायरेक्टरी को संदर्भित करता है, और ‘.datascience’ सबरेडिट को।
अच्छा, तो हमारे पास यह पहचानने का तरीका है कि कौन सी पोस्ट इनबाउंड है और कौन सी आउटबाउंड। अब हमें इसे DOM संरचना में पहचानना है। क्या हम टैग्स, क्लासेस, या IDs के आधार पर DOM में इन पहचानकर्ताओं को खोज सकते हैं? बिल्कुल!
अपने वेब ब्राउज़र में किसी भी ‘self.datascience’ लिंक पर राइट-क्लिक करें और ‘inspect element’ चुनें। अधिकांश आधुनिक ब्राउज़रों में यह बढ़िया टूल होता है जो वेब डेवलपर्स को वेबपेज के स्रोत कोड के प्रासंगिक हिस्सों को गतिशील रूप से देखने देता है। यदि आप Safari पर हैं, तो preferences में डेवलपर टूल्स सक्षम कर लें। आपको एक पैन दिखाई देगा जो उस स्रोत कोड वाले हिस्से पर स्क्रॉल होकर आएगा जो ‘(self.datascience)’ पहचानकर्ता के लिए ज़िम्मेदार है।
पैन में आप देखेंगे कि यह पहचानकर्ता वास्तव में एक एंकर टैग से लोड होता है।
<ahref="/r/datascience">self.datascience</a>संचालित द्वारा
लेकिन यह एक span टैग में घिरा होता है।
<spanclass="domain">
"("
<ahref="/r/datascience">self.datascience</a>
")"
</span>संचालित द्वारा
यह span टैग वही टेक्स्ट समाहित करता है जो हमें पेज पर दिखता है, यानी ‘(self.datascience)’। जैसा कि आप देख सकते हैं, इसे ‘domain’ क्लास दी गई है। आप अन्य सभी लिंक्स भी जाँच सकते हैं कि क्या वे इसी फ़ॉर्मेट का पालन करते हैं—और हाँ; वे करते हैं।
BeautifulSoup के साथ पेज प्राप्त करना
हमें पता है कि पेज पर क्या चाहिए, पर Python से पेज की सामग्री पढ़ें कैसे? तरीका लगभग वैसा ही है जैसा कोई इंसान ब्राउज़र में पेज पढ़ता है।
पहले, हमें ‘requests’ लाइब्रेरी का उपयोग करके वेब पेज मंगाना होगा।
url ="https://old.reddit.com/r/datascience"# Headers to mimic a browser visit
headers ={'User-Agent':'Mozilla/5.0'}# Returns a requests.models.Response object
page = requests.get(url, headers=headers)संचालित द्वारा
अब हमारे पास एक Response ऑब्जेक्ट है जिसमें वेबपेज का कच्चा टेक्स्ट है। अभी तक, हम इससे कुछ कर नहीं सकते। हमारे पास सिर्फ एक विशाल स्ट्रिंग है जिसमें पूरे HTML स्रोत कोड का कंटेंट है। इसे समझने के लिए हमें BeautifulSoup 4 की आवश्यकता होगी।
हेडर्स हमें ब्राउज़र विज़िट की नकल करने देते हैं। चूँकि बॉट को मिलने वाली प्रतिक्रिया ब्राउज़र को मिलने वाली प्रतिक्रिया से अलग हो सकती है, और हमारा संदर्भ ब्राउज़र है, इसलिए ब्राउज़र जैसी प्रतिक्रिया लेना बेहतर है।
BeautifulSoup हमें किसी भी संयोजन—क्लासेस, IDs, या टैग नाम—के आधार पर विशिष्ट टैग खोजने देता है। यह एक सिंटैक्स ट्री बनाकर करता है, पर उसके विवरण हमारे लक्ष्य के लिए प्रासंगिक नहीं हैं (और इस ट्यूटोरियल के दायरे से बाहर हैं)।
तो चलिए वह सिंटैक्स ट्री बना लेते हैं।
soup = BeautifulSoup(page.text,'html.parser')संचालित द्वारा
‘soup’ एक BeautifulSoup ऑब्जेक्ट है जो कच्चे स्रोत कोड की स्ट्रिंग से बनाया गया है। ध्यान रखें कि हमें HTML पार्सर निर्दिष्ट करना होता है। ऐसा इसलिए क्योंकि BeautifulSoup XML से भी soup बना सकता है।
अपने टैग ढूँढना
हमें पता है कि कौन से टैग चाहिए (वे span टैग जिनकी क्लास ‘domain’ है), और हमारे पास soup है। अगला कदम है soup को ट्रैवर्स करना और इन टैग्स की सभी घटनाएँ ढूँढना। BeautifulSoup के साथ यह कितना आसान है, देखकर आपको हँसी आ सकती है।
domains = soup.find_all("span", class_="domain")संचालित द्वारा
अभी हमने क्या किया? हमने soup ऑब्जेक्ट पर ‘find_all’ मेथड कॉल किया, जो अपने भीतर दिए गए पैरामीटर्स के अनुरूप एंकर टैग्स की सभी घटनाएँ ढूँढता है। हमने सिर्फ एक शर्त दी (क्लास ‘domain’ होनी चाहिए), पर हम इसे अन्य चीज़ों के साथ जोड़ सकते हैं, या सिर्फ कोई id भी उपयोग कर सकते हैं।
हम ‘class_ =’ इसलिए उपयोग करते हैं क्योंकि 'class' Python में क्लास परिभाषित करने के लिए आरक्षित कीवर्ड है
यदि आप एक से अधिक पैरामीटर पास करना चाहें, तो बस दूसरे पैरामीटर को उन आर्ग्युमेंट्स की एक डिक्शनरी बना दें, जैसे:
soup.find_all("span",{"class":"domain","height","100px"})संचालित द्वारा
हमारे ‘domains’ लिस्ट में सभी span टैग्स आ गए हैं, पर हमें ‘(self.datascience)’ वाले डोमेन्स चाहिए।
for domain in domains:if domain !="(self.datascience)":continueprint(domain.text)संचालित द्वारा
ठीक है, अब आपको पेज पर पोस्ट्स के उन प्रकारों की सूची दिखनी चाहिए जिनमें ‘(self.datascience)’ नहीं है, वे छोड़कर। पर मूलतः हमें जो चाहिए था, वह हमारे पास है। अब हमारे पास उन सभी पोस्ट्स के संदर्भ हैं जो इनबाउंड हैं।
अपनी जानकारी ढूँढना
यह अच्छी बात है कि हम ‘(self.datascience)’ वाली कुछ पंक्तियाँ प्रिंट कर रहे हैं, लेकिन आगे क्या? अपने आरंभिक लक्ष्य को याद करें: पोस्ट शीर्षक, लेखक, लाइक, और कमेंट्स की संख्या प्राप्त करना।
इसके लिए वापस ब्राउज़र पर जाना होगा। अगर आप हमारे उसी पहचानकर्ता पर फिर से इंस्पेक्टर खोलें, तो दिखेगा कि हमारा span टैग एक div टैग के भीतर नेस्टेड है… जो खुद किसी और div में नेस्टेड है, और इसी तरह। ऊपर तक जाते रहें, तो आप पूरी पोस्ट के पैरेंट div तक पहुँच जाएँगे।
<divclass=" thing id-t3_8qccuv even link self"...>
...
<divclass="entry unvoted"><divclass="top-matter"><pclass="title">
...
<spanclass="domain">
...
</p></div></div></div>संचालित द्वारा
जैसा कि आप देख सकते हैं, सामान्य पैरेंट DOM संरचना में उनसे 4 स्तर ऊपर है। एलिप्सिस (…) अनावश्यक भागों का प्रतिनिधित्व करते हैं। पर अब हमें प्रत्येक domain के लिए उस पोस्ट div का संदर्भ चाहिए। हम BeautifulSoup के मेथड्स से किसी भी एलिमेंट का पैरेंट ढूँढ सकते हैं।
for domain in soup.find_all("span", class_="domain"):if domain !="(self.datascience)":continue
parent_div = domain.parent.parent.parent.parent
print(parent_div.text)संचालित द्वारा
स्क्रिप्ट चलाने पर सभी इनबाउंड पोस्ट्स का टेक्स्ट प्रिंट हो जाएगा। लेकिन लगेगा कि यह कोड अच्छा नहीं दिख रहा। आप सही होंगे। DOM की संरचनात्मक अखंडता पर पूरी तरह निर्भर रहना कभी सुरक्षित नहीं होता। यह ऐसा जुगाड़ है जिसे लगातार अपडेट चाहिए और कोड के रूप में एक टिक-टिक करता टाइम बम है।
इसके बजाय, चलिए हर पोस्ट के पैरेंट div को देखते हैं और देखते हैं कि क्या हम पैरेंट से ही इनबाउंड और आउटबाउंड लिंक अलग कर सकते हैं। हर पैरेंट div में ‘data-domain’ नाम का एक एट्रीब्यूट होता है, जिसका मान ठीक वैसा ही है जैसा हमें चाहिए! सभी इनबाउंड पोस्ट्स का data-domain ‘self.datascience’ सेट होता है।
जैसा कि पहले उल्लेख किया, हम BeautifulSoup में एट्रीब्यूट्स के संयोजन से टैग खोज सकते हैं। हमारे लिए सौभाग्य से, Reddit ने हर पोस्ट के पैरेंट div को ‘thing’ क्लास दी है।
attrs ={'class':'thing','data-domain':'self.datascience'}for post in soup.find_all('div', attrs=attrs):print(post.attrs['data-domain'])संचालित द्वारा
‘attrs’ वेरिएबल एक डिक्शनरी है जिसमें वे एट्रीब्यूट्स और उनके मान हैं जिन्हें हम खोजना चाहते हैं। यह पोस्ट्स को ढूँढने का कहीं अधिक सुरक्षित तरीका है क्योंकि इसमें कम चलते हिस्से हैं। चूँकि हम खोजते समय ही ‘self.datascience’ को आर्ग्युमेंट के रूप में जोड़ रहे हैं, इसलिए अब हमें कोई if स्टेटमेंट लगाकर इटरशन स्किप नहीं करनी पड़ती—हमें गारंटी है कि केवल वही पोस्ट्स मिलेंगी जिनका data-domain ‘self.datascience’ है।
अब जब हमारे पास वांछित पोस्ट्स हैं, तो बस चाइल्ड से जानकारी निकालनी रह जाती है। और यह उतना ही सरल है जितना आप सोच रहे हैं।
Reddit से अपनी जानकारी निकालना
हर पोस्ट के लिए हमें 4 चीजें चाहिए:
शीर्षक
लेखक
लाइक्स
कमेंट्स
यदि हम पोस्ट div की संरचना देखें, तो हमें यह सारी जानकारी मिल जाएगी।
शीर्षक
यह अब तक का सबसे आसान भाग है। हर पोस्ट div में, कुछ लेयर्स के div के भीतर एक पैराग्राफ टैग होता है। इसे खोजना विशेष रूप से आसान है क्योंकि इसमें ‘title’ क्लास लगी होती है।
title = post.find('p', class_="title").text
संचालित द्वारा
‘post’ ऑब्जेक्ट हमारा पहले वाला for लूप के भीतर है। यह भी एक BeautifulSoup ऑब्जेक्ट है, पर इसमें सिर्फ पोस्ट div के भीतर का DOM होता है। ‘find’ मेथड एक ही ऑब्जेक्ट लौटाता है, जबकि 'find_all' उन सभी ऑब्जेक्ट्स की सूची लौटाता है जो मापदंडों पर खरे उतरते हैं। टैग मिलने के बाद, हमें केवल शीर्षक का स्ट्रिंग चाहिए, इसलिए हम उसकी text प्रॉपर्टी पढ़ते हैं। अन्य एट्रीब्यूट्स हम ‘object.attrs[‘attribute’]’ से पढ़ सकते हैं।
लेखक
यह भी काफ़ी सरल है—किसी भी पोस्ट शीर्षक के नीचे लेखक के नाम पर इंस्पेक्टर खोलें। आप देखेंगे कि लेखक का नाम ‘author’ क्लास वाले एंकर टैग में होता है।
author = post.find('a', class_='author').text
संचालित द्वारा
कमेंट्स
इसमें थोड़ा अतिरिक्त काम है, पर यह भी सरल है। हम कमेंट्स उसी तरह ढूँढ सकते हैं जैसे शीर्षक और लेखक।
comments = post.find('a', class_='comments').text
संचालित द्वारा
इसे चलाने पर आपको कुछ ऐसा मिलेगा: “49 comments”。 यह ठीक है, पर बेहतर होगा कि हमें सिर्फ संख्या मिले। इसके लिए हमें थोड़ा और Python उपयोग करना होगा।
यदि हम Python का ‘str.split()’ फ़ंक्शन उपयोग करें, तो यह स्ट्रिंग को स्पेस पर बाँटकर तत्वों की एक ऐरे लौटाएगा। हमारे मामले में हमें सूची ‘[“49", “comments”]’ मिलेगी। बढ़िया! अब, हमें केवल पहला तत्व लेना है और स्टोर करना है। इसके लिए हम अपनी लाइन में फ़ंक्शन्स जोड़ देते हैं।
comments = post.find('a', class_='comments').text.split()[0]संचालित द्वारा
पर हम अभी भी पूरे नहीं हुए, क्योंकि कभी-कभी हमें संख्या नहीं मिलती—‘comment’ मिलता है। यह तब होता है जब पोस्ट पर कोई कमेंट नहीं होता। चूँकि हमें यह पता है, हमें केवल यह जाँचना है कि परिणाम ‘comments’ तो नहीं आ रहा, और उसे ‘0’ से बदल देना है।
लाइक्स की संख्या ढूँढना बहुत आसान है, और ऊपर के लॉजिक से मेल खाता है।
likes = post.find("div", attrs={"class":"score likes"}).text
संचालित द्वारा
यहाँ आप देखेंगे कि हमने दो क्लासेस का संयोजन इस्तेमाल किया है। ऐसा इसलिए क्योंकि ‘score’ या ‘likes’ क्लास वाले कई और div हैं, पर ‘score’ और ‘likes’ के संयोजन वाला केवल एक है।
यदि लाइक्स की संख्या 0 है, तो हमें 0 मिलता है। पर कुछ अजीब तब होता है जब पोस्ट इतनी नई हो कि उसे अभी तक लाइक्स न मिले हों—तब हमें “•” मिलता है। चलिए इसे “None” से बदल देते हैं ताकि हमारे अंतिम परिणामों में भ्रम न रहे।
अब तक, हमारे पास एक लूप है जो वेबपेज की हर पोस्ट के लिए शीर्षक, लेखक, लाइक्स और कमेंट्स निकालता है। CSV फ़ाइलें लिखने-पढ़ने के लिए Python में ‘csv’ नाम का बेहतरीन बिल्ट-इन मॉड्यूल है—पाइथोनिक तरीका: इसे सरल रखें। खैर, हमें बस लूप ब्लॉक के अंत में एक लाइन जोड़नी है जो पोस्ट के विवरण को CSV फ़ाइल में जोड़ दे।
counter =1for post in posts:...
post_line =[counter, title, author, likes, comments]withopen('output.csv','a')as f:
writer = csv.writer(f)
writer.writerow(post_line)
counter +=1संचालित द्वारा
काफ़ी सीधा-सादा है, है न? ‘post_line’ कॉमा से अलग करने के लिए आवश्यक तत्वों की एक ऐरे बनाता है। ‘counter’ वेरिएबल इस बात का हिसाब रखता है कि हमने कितनी पोस्ट्स रिकॉर्ड की हैं।
अगले पेज पर जाना
चूँकि हम रिकॉर्ड की जा रही पोस्ट्स की संख्या गिन रहे हैं, हमें बस अपनी पूरी लॉजिक को एक और लूप में रखना है जो तब तक नए पेज मंगाता रहे जब तक किसी निश्चित संख्या की पोस्ट्स रिकॉर्ड न हो जाएँ।
counter =1while(counter <=100):for post in posts:# Getting the title, author, ...# Writing to CSV and incrementing counter...
next_button = soup.find("span", class_="next-button")
next_page_link = next_button.find("a").attrs['href']
time.sleep(2)
page = requests.get(next_page_link, headers=headers)
soup = BeautifulSoup(page.text,'html.parser')संचालित द्वारा
हमने कई काम एक साथ कर दिए, है न? एक-एक लाइन देखकर समझते हैं। पहले, हमने ‘counter’ वेरिएबल को एक ब्लॉक ऊपर ले जाया ताकि while लूप उसे उपयोग कर सके।
अगला, हमें for लूप समझ में आता है, पर बाकी के बारे में क्या? ‘next_button’ वेरिएबल ‘next’ बटन को ढूँढकर स्टोर करता है। उसके बाद, हम उसके भीतर के एंकर टैग को ढूँढते हैं और 'href' एट्रीब्यूट लेते हैं; जिसे हम ‘next_page_link’ में स्टोर करते हैं।
हम इस लिंक से अगला पेज मंगा सकते हैं और उसे ‘page’ में स्टोर कर सकते हैं, और BeautifulSoup से एक नई soup बना सकते हैं।
ऊपर दिया स्निपेट 100 पर रुकता है, पर आप इसे किसी भी संख्या की पोस्ट्स पर रोक सकते हैं।
जिम्मेदारी से स्क्रैप करना
ऊपर जिस लाइन पर हमने बात नहीं की, वह है ‘time.sleep(2)’। ऐसा इसलिए क्योंकि वह लाइन अपने आप में एक सेक्शन की हकदार है। किसी भी वेब सर्वर के संसाधन सीमित होते हैं, इसलिए यह हमारी ज़िम्मेदारी है कि हम उन्हें पूरा इस्तेमाल न कर लें। चंद सेकंडों में सैकड़ों पेज मंगाना न केवल आपको बैन करवा सकता है, बल्कि यह शिष्ट भी नहीं है।
ध्यान रखें कि वेबसाइट का आपको स्क्रैप करने देना काफ़ी बड़ी बात है—अगर वे चाहें, तो 10–20 रिक्वेस्ट में ही बॉट्स पकड़ सकते हैं, या Python के रिक्वेस्ट ऑब्जेक्ट के आधार पर भी आपको पकड़ सकते हैं। वे आपको बिना IP रोटेट किए स्क्रैप करने देते हैं, तो आपको भी अपने बॉट को धीमा करके उनकी सेवा करनी चाहिए।
किसी वेबसाइट की क्रॉल नीति आप उसकी robots.txt फ़ाइल देखकर पा सकते हैं। यह आम तौर पर वेबसाइट की रूट पर मिलती है (उदा. http://www.reddit.com/robots.txt)।
आगे क्या?
खैर, जो भी आप चाहें। जैसा कि हमने अभी सिद्ध किया, वेब पर जो कुछ भी दिखता है, उसे स्क्रैप कर स्थानीय रूप से स्टोर किया जा सकता है। हमने जो जानकारी इकट्ठी की है, उसका आप ढेर सारे उद्देश्यों के लिए उपयोग कर सकते हैं। सिर्फ़ वे चार चीज़ें जिन्हें हमने ढूँढा, उनसे भी हम कई निष्कर्ष निकाल सकते हैं।
अपनी जानकारी का और विश्लेषण करके, हम जान सकते हैं कि किस तरह की Reddit पोस्ट्स को सबसे अधिक लाइक मिलते हैं, वे किन शब्दों को समेटे होती हैं, उन्हें कौन पोस्ट करता है। या उल्टा, हम लाइक्स-टू-कमेंट्स अनुपात का विश्लेषण करके विवाद का सूचकांक बना सकते हैं।
मान लीजिए किसी पोस्ट पर बहुत सारे कमेंट्स हैं, पर लाइक नहीं। इसका अर्थ प्रायः यह होता है कि पोस्ट में ऐसा कुछ है जो लोगों के भीतर किसी तार को छेड़ता है, पर जरूरी नहीं कि उन्हें वह पसंद हो।
संभावनाएँ बहुत हैं, और जानकारी का उपयोग कैसे करना है यह आपके ऊपर है।
Python के साथ डेटा विश्लेषण की बुनियादी बातें सिर्फ चार घंटे में सीखें। यह ऑनलाइन पाठ्यक्रम Python इंटरफ़ेस का परिचय देगा और लोकप्रिय पैकेजों का अन्वेषण करेगा।
हम जो स्क्रिप्ट लिखेंगे उसका तैयार, कार्यरत उदाहरण आपको यहाँ मिल जाएगा।
वेब स्क्रैपिंग क्या है?
ठीक है, तो आखिर वेब स्क्रैपिंग है क्या? नाम से ही स्पष्ट है—यह वेबपेजों से डेटा ‘स्क्रैप’ या निकालने की एक विधि है। आपके ब्राउज़र में इंटरनेट पर जो कुछ भी दिखता है, इस ट्यूटोरियल सहित, उसे आप अपने स्थानीय हार्ड ड्राइव पर स्क्रैप कर सकते हैं।
वेब स्क्रैपिंग के कई उपयोग हैं। किसी भी डेटा विश्लेषण में पहला कदम डेटा प्राप्त करना होता है। इंटरनेट मानव इतिहास और ज्ञान का एक विशाल भंडार है, और आपके पास जो भी जानकारी चाहिए उसे निकालने और उसका इच्छानुसार उपयोग करने के साधन हैं।
अपने ट्यूटोरियल में, हम Python और BeautifulSoup 4 पैकेज का उपयोग करके किसी सबरेडिट से जानकारी लेंगे। हमारा लक्ष्य datascience सबरेडिट है। हम इस सबरेडिट पर पहली 1000 पोस्ट्स लेना चाहते हैं और उन्हें CSV फ़ाइल में निर्यात करना चाहते हैं। हम जानना चाहते हैं कि इसे किसने पोस्ट किया, साथ ही इसे कितने लाइक और कमेंट मिले।
इस ट्यूटोरियल में हम क्या कवर करेंगे:
requestsका उपयोग करके वेब पेज प्राप्त करनानोट: हम Reddit की पुरानी साइट का उपयोग करेंगे क्योंकि वह लोड होने में हल्की है, और इस प्रकार आपकी मशीन पर कम भार डालती है।
पूर्वापेक्षाएँ
यह ट्यूटोरियल मानकर चलता है कि आप निम्न बातों से परिचित हैं:
आप उपर्युक्त कौशल DataCamp के Python शुरुआती कोर्स में सीख सकते हैं। यह कहते हुए, यहाँ उपयोग की गई संकल्पनाएँ बहुत न्यूनतम हैं, और बहुत कम Python ज्ञान के साथ भी आप काम चला सकते हैं।
अब जब यह हो गया, तो हम अपने वेब स्क्रैपर बनाने के पहले हिस्से पर बढ़ सकते हैं। वास्तव में, किसी भी Python स्क्रिप्ट का पहला हिस्सा: imports।
अपने स्क्रैपर में, हम निम्न पैकेजों का उपयोग करेंगे:
requestsbeautifulsoup4आप इन पैकेजों को pip से, इस तरह इंस्टॉल कर सकते हैं:
पैकेज डाउनलोड करने के बाद, उन्हें अपने कोड में import कर लें।
हम अपने परिणामों को CSV फ़ाइल में लिखने के लिए Python के बिल्ट-इन
csvमॉड्यूल का उपयोग करेंगे। आपने ऊपर दिए स्निपेट में एक अजीब सी बात देखी होगी। यानी, हमनेbeautifulsoup4नाम का पैकेज डाउनलोड किया, लेकिनbs4नाम के मॉड्यूल से import किया। यह Python में वैध है, और यद्यपि आमतौर पर इसे अच्छा नहीं माना जाता, यह किसी नियम के विरुद्ध नहीं है।प्लेटफ़ॉर्म नीतियों पर महत्वपूर्ण नोट
अगले चरणों में बताई गई स्क्रैपिंग तकनीकों का उपयोग करने से पहले, Reddit या किसी अन्य वेबसाइट जिसकी आप स्क्रैपिंग करना चाहते हैं, की वर्तमान सेवा शर्तें अवश्य जाँचें। वेबसाइट नीतियाँ समय के साथ बदल सकती हैं। सितंबर 2024 का Reddit User Agreement पूर्व लिखित सहमति के बिना स्क्रैपिंग पर रोक लगाता है (धारा 7 देखें)। आगे बढ़ने से पहले हमेशा सुनिश्चित करें कि आप साइट के नवीनतम उपयोग दिशानिर्देशों का पालन कर रहे हैं।
Reddit को क्रॉल करने के पहले कदम
तो हमारा पर्यावरण सेटअप हो चुका है। अब हमें उस वेबपेज का URL चाहिए जिसे हम स्क्रैप करना चाहते हैं। अपने ट्यूटोरियल के लिए, हम Reddit के ‘datascience’ सबरेडिट का उपयोग कर रहे हैं। स्क्रिप्ट लिखना शुरू करने से पहले, थोड़ा फील्डवर्क करना होगा। एक वेब ब्राउज़र खोलें, और संबंधित सबरेडिट पर जाएँ।
ध्यान दें कि हम अपने स्क्रैपर के लिए सबरेडिट के पुराने संस्करण का उपयोग करेंगे। नए संस्करण में कुछ महत्त्वपूर्ण जानकारी वेबपेज के अंदरूनी हिस्से में छिपी रहती है। नई साइट से भी यह जानकारी निकाली जा सकती है, लेकिन सरलता के लिए, हम पुराने संस्करण का उपयोग करेंगे जिसमें सब कुछ साफ़-साफ़ दिखता है।
लिंक खोलते ही आपको जानकारी का सैलाब दिखेगा। इसमें से हमें क्या चाहिए? सभी लिंक्स को जाँचना शुरू करें, तो पता चलेगा कि Reddit पोस्ट्स दो प्रकार की होती हैं:
इनबाउंड लिंक वे होते हैं जो Reddit के भीतर की सामग्री की ओर इशारा करते हैं, और आउटबाउंड इसके उलट। यह इसलिए महत्त्वपूर्ण है क्योंकि हमें केवल इनबाउंड लिंक चाहिए। यानी वे पोस्ट्स जिनमें उपयोगकर्ताओं द्वारा लिखा गया टेक्स्ट हो, न कि केवल अन्य वेबसाइटों के लिंक।
तो हमें पता है कि क्या चाहिए, अब इसे निकालें कैसे? यदि आप पोस्ट्स के शीर्षक देखते हैं, तो उनके बाद ब्रैकेट में कुछ टेक्स्ट आता है। जिन पोस्ट्स में हमारी दिलचस्पी है, उनके बाद ‘(self.datascience)’ आता है। तर्कसंगत रूप से, माना जा सकता है कि ‘self’ Reddit की रूट डायरेक्टरी को संदर्भित करता है, और ‘.datascience’ सबरेडिट को।
अच्छा, तो हमारे पास यह पहचानने का तरीका है कि कौन सी पोस्ट इनबाउंड है और कौन सी आउटबाउंड। अब हमें इसे DOM संरचना में पहचानना है। क्या हम टैग्स, क्लासेस, या IDs के आधार पर DOM में इन पहचानकर्ताओं को खोज सकते हैं? बिल्कुल!
अपने वेब ब्राउज़र में किसी भी ‘self.datascience’ लिंक पर राइट-क्लिक करें और ‘inspect element’ चुनें। अधिकांश आधुनिक ब्राउज़रों में यह बढ़िया टूल होता है जो वेब डेवलपर्स को वेबपेज के स्रोत कोड के प्रासंगिक हिस्सों को गतिशील रूप से देखने देता है। यदि आप Safari पर हैं, तो preferences में डेवलपर टूल्स सक्षम कर लें। आपको एक पैन दिखाई देगा जो उस स्रोत कोड वाले हिस्से पर स्क्रॉल होकर आएगा जो ‘(self.datascience)’ पहचानकर्ता के लिए ज़िम्मेदार है।
पैन में आप देखेंगे कि यह पहचानकर्ता वास्तव में एक एंकर टैग से लोड होता है।
लेकिन यह एक span टैग में घिरा होता है।
यह span टैग वही टेक्स्ट समाहित करता है जो हमें पेज पर दिखता है, यानी ‘(self.datascience)’। जैसा कि आप देख सकते हैं, इसे ‘domain’ क्लास दी गई है। आप अन्य सभी लिंक्स भी जाँच सकते हैं कि क्या वे इसी फ़ॉर्मेट का पालन करते हैं—और हाँ; वे करते हैं।
BeautifulSoup के साथ पेज प्राप्त करना
हमें पता है कि पेज पर क्या चाहिए, पर Python से पेज की सामग्री पढ़ें कैसे? तरीका लगभग वैसा ही है जैसा कोई इंसान ब्राउज़र में पेज पढ़ता है।
पहले, हमें ‘requests’ लाइब्रेरी का उपयोग करके वेब पेज मंगाना होगा।
अब हमारे पास एक Response ऑब्जेक्ट है जिसमें वेबपेज का कच्चा टेक्स्ट है। अभी तक, हम इससे कुछ कर नहीं सकते। हमारे पास सिर्फ एक विशाल स्ट्रिंग है जिसमें पूरे HTML स्रोत कोड का कंटेंट है। इसे समझने के लिए हमें BeautifulSoup 4 की आवश्यकता होगी।
हेडर्स हमें ब्राउज़र विज़िट की नकल करने देते हैं। चूँकि बॉट को मिलने वाली प्रतिक्रिया ब्राउज़र को मिलने वाली प्रतिक्रिया से अलग हो सकती है, और हमारा संदर्भ ब्राउज़र है, इसलिए ब्राउज़र जैसी प्रतिक्रिया लेना बेहतर है।
BeautifulSoup हमें किसी भी संयोजन—क्लासेस, IDs, या टैग नाम—के आधार पर विशिष्ट टैग खोजने देता है। यह एक सिंटैक्स ट्री बनाकर करता है, पर उसके विवरण हमारे लक्ष्य के लिए प्रासंगिक नहीं हैं (और इस ट्यूटोरियल के दायरे से बाहर हैं)।
तो चलिए वह सिंटैक्स ट्री बना लेते हैं।
‘soup’ एक BeautifulSoup ऑब्जेक्ट है जो कच्चे स्रोत कोड की स्ट्रिंग से बनाया गया है। ध्यान रखें कि हमें HTML पार्सर निर्दिष्ट करना होता है। ऐसा इसलिए क्योंकि BeautifulSoup XML से भी soup बना सकता है।
अपने टैग ढूँढना
हमें पता है कि कौन से टैग चाहिए (वे span टैग जिनकी क्लास ‘domain’ है), और हमारे पास soup है। अगला कदम है soup को ट्रैवर्स करना और इन टैग्स की सभी घटनाएँ ढूँढना। BeautifulSoup के साथ यह कितना आसान है, देखकर आपको हँसी आ सकती है।
अभी हमने क्या किया? हमने soup ऑब्जेक्ट पर ‘find_all’ मेथड कॉल किया, जो अपने भीतर दिए गए पैरामीटर्स के अनुरूप एंकर टैग्स की सभी घटनाएँ ढूँढता है। हमने सिर्फ एक शर्त दी (क्लास ‘domain’ होनी चाहिए), पर हम इसे अन्य चीज़ों के साथ जोड़ सकते हैं, या सिर्फ कोई id भी उपयोग कर सकते हैं।
हम ‘class_ =’ इसलिए उपयोग करते हैं क्योंकि 'class' Python में क्लास परिभाषित करने के लिए आरक्षित कीवर्ड है
यदि आप एक से अधिक पैरामीटर पास करना चाहें, तो बस दूसरे पैरामीटर को उन आर्ग्युमेंट्स की एक डिक्शनरी बना दें, जैसे:
हमारे ‘domains’ लिस्ट में सभी span टैग्स आ गए हैं, पर हमें ‘(self.datascience)’ वाले डोमेन्स चाहिए।
ठीक है, अब आपको पेज पर पोस्ट्स के उन प्रकारों की सूची दिखनी चाहिए जिनमें ‘(self.datascience)’ नहीं है, वे छोड़कर। पर मूलतः हमें जो चाहिए था, वह हमारे पास है। अब हमारे पास उन सभी पोस्ट्स के संदर्भ हैं जो इनबाउंड हैं।
अपनी जानकारी ढूँढना
यह अच्छी बात है कि हम ‘(self.datascience)’ वाली कुछ पंक्तियाँ प्रिंट कर रहे हैं, लेकिन आगे क्या? अपने आरंभिक लक्ष्य को याद करें: पोस्ट शीर्षक, लेखक, लाइक, और कमेंट्स की संख्या प्राप्त करना।
इसके लिए वापस ब्राउज़र पर जाना होगा। अगर आप हमारे उसी पहचानकर्ता पर फिर से इंस्पेक्टर खोलें, तो दिखेगा कि हमारा span टैग एक div टैग के भीतर नेस्टेड है… जो खुद किसी और div में नेस्टेड है, और इसी तरह। ऊपर तक जाते रहें, तो आप पूरी पोस्ट के पैरेंट div तक पहुँच जाएँगे।
जैसा कि आप देख सकते हैं, सामान्य पैरेंट DOM संरचना में उनसे 4 स्तर ऊपर है। एलिप्सिस (…) अनावश्यक भागों का प्रतिनिधित्व करते हैं। पर अब हमें प्रत्येक domain के लिए उस पोस्ट div का संदर्भ चाहिए। हम BeautifulSoup के मेथड्स से किसी भी एलिमेंट का पैरेंट ढूँढ सकते हैं।
स्क्रिप्ट चलाने पर सभी इनबाउंड पोस्ट्स का टेक्स्ट प्रिंट हो जाएगा। लेकिन लगेगा कि यह कोड अच्छा नहीं दिख रहा। आप सही होंगे। DOM की संरचनात्मक अखंडता पर पूरी तरह निर्भर रहना कभी सुरक्षित नहीं होता। यह ऐसा जुगाड़ है जिसे लगातार अपडेट चाहिए और कोड के रूप में एक टिक-टिक करता टाइम बम है।
इसके बजाय, चलिए हर पोस्ट के पैरेंट div को देखते हैं और देखते हैं कि क्या हम पैरेंट से ही इनबाउंड और आउटबाउंड लिंक अलग कर सकते हैं। हर पैरेंट div में ‘data-domain’ नाम का एक एट्रीब्यूट होता है, जिसका मान ठीक वैसा ही है जैसा हमें चाहिए! सभी इनबाउंड पोस्ट्स का data-domain ‘self.datascience’ सेट होता है।
जैसा कि पहले उल्लेख किया, हम BeautifulSoup में एट्रीब्यूट्स के संयोजन से टैग खोज सकते हैं। हमारे लिए सौभाग्य से, Reddit ने हर पोस्ट के पैरेंट div को ‘thing’ क्लास दी है।
‘attrs’ वेरिएबल एक डिक्शनरी है जिसमें वे एट्रीब्यूट्स और उनके मान हैं जिन्हें हम खोजना चाहते हैं। यह पोस्ट्स को ढूँढने का कहीं अधिक सुरक्षित तरीका है क्योंकि इसमें कम चलते हिस्से हैं। चूँकि हम खोजते समय ही ‘self.datascience’ को आर्ग्युमेंट के रूप में जोड़ रहे हैं, इसलिए अब हमें कोई if स्टेटमेंट लगाकर इटरशन स्किप नहीं करनी पड़ती—हमें गारंटी है कि केवल वही पोस्ट्स मिलेंगी जिनका data-domain ‘self.datascience’ है।
अब जब हमारे पास वांछित पोस्ट्स हैं, तो बस चाइल्ड से जानकारी निकालनी रह जाती है। और यह उतना ही सरल है जितना आप सोच रहे हैं।
Reddit से अपनी जानकारी निकालना
हर पोस्ट के लिए हमें 4 चीजें चाहिए:
यदि हम पोस्ट div की संरचना देखें, तो हमें यह सारी जानकारी मिल जाएगी।
शीर्षक
यह अब तक का सबसे आसान भाग है। हर पोस्ट div में, कुछ लेयर्स के div के भीतर एक पैराग्राफ टैग होता है। इसे खोजना विशेष रूप से आसान है क्योंकि इसमें ‘title’ क्लास लगी होती है।
‘post’ ऑब्जेक्ट हमारा पहले वाला for लूप के भीतर है। यह भी एक BeautifulSoup ऑब्जेक्ट है, पर इसमें सिर्फ पोस्ट div के भीतर का DOM होता है। ‘find’ मेथड एक ही ऑब्जेक्ट लौटाता है, जबकि 'find_all' उन सभी ऑब्जेक्ट्स की सूची लौटाता है जो मापदंडों पर खरे उतरते हैं। टैग मिलने के बाद, हमें केवल शीर्षक का स्ट्रिंग चाहिए, इसलिए हम उसकी text प्रॉपर्टी पढ़ते हैं। अन्य एट्रीब्यूट्स हम ‘object.attrs[‘attribute’]’ से पढ़ सकते हैं।
लेखक
यह भी काफ़ी सरल है—किसी भी पोस्ट शीर्षक के नीचे लेखक के नाम पर इंस्पेक्टर खोलें। आप देखेंगे कि लेखक का नाम ‘author’ क्लास वाले एंकर टैग में होता है।
कमेंट्स
इसमें थोड़ा अतिरिक्त काम है, पर यह भी सरल है। हम कमेंट्स उसी तरह ढूँढ सकते हैं जैसे शीर्षक और लेखक।
इसे चलाने पर आपको कुछ ऐसा मिलेगा: “49 comments”。 यह ठीक है, पर बेहतर होगा कि हमें सिर्फ संख्या मिले। इसके लिए हमें थोड़ा और Python उपयोग करना होगा।
यदि हम Python का ‘str.split()’ फ़ंक्शन उपयोग करें, तो यह स्ट्रिंग को स्पेस पर बाँटकर तत्वों की एक ऐरे लौटाएगा। हमारे मामले में हमें सूची ‘[“49", “comments”]’ मिलेगी। बढ़िया! अब, हमें केवल पहला तत्व लेना है और स्टोर करना है। इसके लिए हम अपनी लाइन में फ़ंक्शन्स जोड़ देते हैं।
पर हम अभी भी पूरे नहीं हुए, क्योंकि कभी-कभी हमें संख्या नहीं मिलती—‘comment’ मिलता है। यह तब होता है जब पोस्ट पर कोई कमेंट नहीं होता। चूँकि हमें यह पता है, हमें केवल यह जाँचना है कि परिणाम ‘comments’ तो नहीं आ रहा, और उसे ‘0’ से बदल देना है।
लाइक्स
लाइक्स की संख्या ढूँढना बहुत आसान है, और ऊपर के लॉजिक से मेल खाता है।
यहाँ आप देखेंगे कि हमने दो क्लासेस का संयोजन इस्तेमाल किया है। ऐसा इसलिए क्योंकि ‘score’ या ‘likes’ क्लास वाले कई और div हैं, पर ‘score’ और ‘likes’ के संयोजन वाला केवल एक है।
यदि लाइक्स की संख्या 0 है, तो हमें 0 मिलता है। पर कुछ अजीब तब होता है जब पोस्ट इतनी नई हो कि उसे अभी तक लाइक्स न मिले हों—तब हमें “•” मिलता है। चलिए इसे “None” से बदल देते हैं ताकि हमारे अंतिम परिणामों में भ्रम न रहे।
अपने परिणाम CSV में लिखना
अब तक, हमारे पास एक लूप है जो वेबपेज की हर पोस्ट के लिए शीर्षक, लेखक, लाइक्स और कमेंट्स निकालता है। CSV फ़ाइलें लिखने-पढ़ने के लिए Python में ‘csv’ नाम का बेहतरीन बिल्ट-इन मॉड्यूल है—पाइथोनिक तरीका: इसे सरल रखें। खैर, हमें बस लूप ब्लॉक के अंत में एक लाइन जोड़नी है जो पोस्ट के विवरण को CSV फ़ाइल में जोड़ दे।
काफ़ी सीधा-सादा है, है न? ‘post_line’ कॉमा से अलग करने के लिए आवश्यक तत्वों की एक ऐरे बनाता है। ‘counter’ वेरिएबल इस बात का हिसाब रखता है कि हमने कितनी पोस्ट्स रिकॉर्ड की हैं।
अगले पेज पर जाना
चूँकि हम रिकॉर्ड की जा रही पोस्ट्स की संख्या गिन रहे हैं, हमें बस अपनी पूरी लॉजिक को एक और लूप में रखना है जो तब तक नए पेज मंगाता रहे जब तक किसी निश्चित संख्या की पोस्ट्स रिकॉर्ड न हो जाएँ।
हमने कई काम एक साथ कर दिए, है न? एक-एक लाइन देखकर समझते हैं। पहले, हमने ‘counter’ वेरिएबल को एक ब्लॉक ऊपर ले जाया ताकि while लूप उसे उपयोग कर सके।
अगला, हमें for लूप समझ में आता है, पर बाकी के बारे में क्या? ‘next_button’ वेरिएबल ‘next’ बटन को ढूँढकर स्टोर करता है। उसके बाद, हम उसके भीतर के एंकर टैग को ढूँढते हैं और 'href' एट्रीब्यूट लेते हैं; जिसे हम ‘next_page_link’ में स्टोर करते हैं।
हम इस लिंक से अगला पेज मंगा सकते हैं और उसे ‘page’ में स्टोर कर सकते हैं, और BeautifulSoup से एक नई soup बना सकते हैं।
ऊपर दिया स्निपेट 100 पर रुकता है, पर आप इसे किसी भी संख्या की पोस्ट्स पर रोक सकते हैं।
जिम्मेदारी से स्क्रैप करना
ऊपर जिस लाइन पर हमने बात नहीं की, वह है ‘time.sleep(2)’। ऐसा इसलिए क्योंकि वह लाइन अपने आप में एक सेक्शन की हकदार है। किसी भी वेब सर्वर के संसाधन सीमित होते हैं, इसलिए यह हमारी ज़िम्मेदारी है कि हम उन्हें पूरा इस्तेमाल न कर लें। चंद सेकंडों में सैकड़ों पेज मंगाना न केवल आपको बैन करवा सकता है, बल्कि यह शिष्ट भी नहीं है।
ध्यान रखें कि वेबसाइट का आपको स्क्रैप करने देना काफ़ी बड़ी बात है—अगर वे चाहें, तो 10–20 रिक्वेस्ट में ही बॉट्स पकड़ सकते हैं, या Python के रिक्वेस्ट ऑब्जेक्ट के आधार पर भी आपको पकड़ सकते हैं। वे आपको बिना IP रोटेट किए स्क्रैप करने देते हैं, तो आपको भी अपने बॉट को धीमा करके उनकी सेवा करनी चाहिए।
किसी वेबसाइट की क्रॉल नीति आप उसकी robots.txt फ़ाइल देखकर पा सकते हैं। यह आम तौर पर वेबसाइट की रूट पर मिलती है (उदा. http://www.reddit.com/robots.txt)।
आगे क्या?
खैर, जो भी आप चाहें। जैसा कि हमने अभी सिद्ध किया, वेब पर जो कुछ भी दिखता है, उसे स्क्रैप कर स्थानीय रूप से स्टोर किया जा सकता है। हमने जो जानकारी इकट्ठी की है, उसका आप ढेर सारे उद्देश्यों के लिए उपयोग कर सकते हैं। सिर्फ़ वे चार चीज़ें जिन्हें हमने ढूँढा, उनसे भी हम कई निष्कर्ष निकाल सकते हैं।
अपनी जानकारी का और विश्लेषण करके, हम जान सकते हैं कि किस तरह की Reddit पोस्ट्स को सबसे अधिक लाइक मिलते हैं, वे किन शब्दों को समेटे होती हैं, उन्हें कौन पोस्ट करता है। या उल्टा, हम लाइक्स-टू-कमेंट्स अनुपात का विश्लेषण करके विवाद का सूचकांक बना सकते हैं।
मान लीजिए किसी पोस्ट पर बहुत सारे कमेंट्स हैं, पर लाइक नहीं। इसका अर्थ प्रायः यह होता है कि पोस्ट में ऐसा कुछ है जो लोगों के भीतर किसी तार को छेड़ता है, पर जरूरी नहीं कि उन्हें वह पसंद हो।
संभावनाएँ बहुत हैं, और जानकारी का उपयोग कैसे करना है यह आपके ऊपर है।
यदि आपको यह ट्यूटोरियल पसंद आया हो, तो हमारे BeautifulSoup के साथ Amazon स्क्रैपिंग गाइड, और हमारी Python कोर्स की शृंखला भी देखें।