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

Python के लिए Scrapy का उपयोग कर वेब क्रॉलर बनाना

Scrapy के साथ वेब क्रॉलर विकसित करें—एक शक्तिशाली फ्रेमवर्क जो वेब डेटा निकालने, प्रोसेस करने और स्टोर करने में मदद करता है।
· 14 मि॰ पढ़ें

AI के साथ खोजें

यदि आप Python में वेब स्क्रैपिंग का एक ओवरव्यू चाहते हैं, तो DataCamp का Web Scraping with Python कोर्स देखें।

इस ट्यूटोरियल में, आप Scrapy का उपयोग करना सीखेंगे, जो एक Python फ्रेमवर्क है जिसकी मदद से आप बड़े पैमाने पर डेटा संभाल सकते हैं! आप Scrapy को एक वेब स्क्रेपर बनाकर सीखेंगे जो AliExpress.com (एक ई-कॉमर्स वेबसाइट) के लिए होगा। चलिए स्क्रैपिंग शुरू करते हैं!

बुनियादी HTML और CSS का ज्ञान इस ट्यूटोरियल को अधिक आसानी और तेजी से समझने में मदद करेगा। HTML और CSS पर यह लेख एक त्वरित रिफ्रेशर के लिए पढ़ें।

Scrapy का ओवरव्यू

scrapy overview
Source

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

आप इंटरनेट पर जो भी वेब पेज देखते हैं, उसे जानकारी के लिए क्रॉल किया जा सकता है और वेब पेज पर दिखने वाली कोई भी चीज़ निकाली जा सकती है [2]। हर वेब पेज की अपनी संरचना और वेब एलिमेंट्स होते हैं, जिनके कारण आपको निकाले जा रहे वेब पेज के अनुसार अपने वेब क्रॉलर/स्पाइडर्स लिखने पड़ते हैं।

Scrapy एक शक्तिशाली फ्रेमवर्क देता है जो डेटा निकालता है, उसे प्रोसेस करता है और फिर सेव करता है।

Scrapy में spiders होते हैं, जो स्वयं-निहित क्रॉलर होते हैं और उन्हें निर्देशों का एक सेट दिया जाता है [1]। Scrapy में डेवलपर्स को अपना कोड पुन: उपयोग करने की सुविधा देकर बड़े क्रॉलिंग प्रोजेक्ट्स बनाना और स्केल करना आसान होता है।

Scrapy बनाम BeautifulSoup

इस खंड में, आप सर्वाधिक उपयोग होने वाले वेब स्क्रैपिंग टूल BeautifulSoup का ओवरव्यू और उसकी Scrapy से तुलना देखेंगे।

Scrapy वेब स्क्रैपिंग के लिए एक Python फ्रेमवर्क है जो डेवलपर्स को कोड मेंटेनेंस की चिंता किए बिना एक संपूर्ण पैकेज प्रदान करता है।

Beautiful Soup भी वेब स्क्रैपिंग के लिए व्यापक रूप से इस्तेमाल होता है। यह HTML और XML दस्तावेज़ों को पार्स करने और उनसे डेटा निकालने के लिए एक Python पैकेज है। यह Python 2.6+ और Python 3 के लिए उपलब्ध है।

संक्षेप में इनके बीच कुछ अंतर इस प्रकार हैं:

ScrapyBeautifulSoup
क्षमता---
Scrapy वेब पेज डाउनलोड करने, उन्हें प्रोसेस करने और फाइलों व डेटाबेस में सेव करने का पूरा पैकेज हैBeautifulSoup मूल रूप से एक HTML और XML पार्सर है और URLs खोलने व परिणाम स्टोर करने के लिए अतिरिक्त लाइब्रेरीज़ जैसे requests, urlib2 की ज़रूरत होती है [6]
सीखने की अवस्था---
Scrapy वेब स्क्रैपिंग के लिए पावरहाउस है और वेब पेज स्क्रैप करने के कई तरीके देता है। इसे सीखने और समझने में अधिक समय लगता है, लेकिन एक बार सीख लेने पर यह केवल एक लाइन के कमांड से वेब क्रॉलर बनाना और चलाना आसान कर देता है। Scrapy में माहिर बनने में अभ्यास और समय लग सकता है।प्रोग्रामिंग में नए लोगों के लिए BeautifulSoup अपेक्षाकृत आसान है और छोटे कार्य कम समय में कर सकता है
गति और लोड---
Scrapy बड़े काम बहुत आसानी से कर सकता है। यह URLs के एक समूह को उनके आकार पर निर्भर करते हुए एक मिनट से भी कम में क्रॉल कर सकता है और यह बहुत स्मूद तरीके से करता है क्योंकि यह Twister का उपयोग करता है जो कंकरेन्सी के लिए asynchronously (non-blocking) काम करता है।BeautifulSoup सरल स्क्रैपिंग कार्यों के लिए प्रभावी है। यदि आप multiprocessing उपयोग नहीं करते, तो यह Scrapy से धीमा है।
कार्यक्षमता बढ़ाना---
Scrapy Item pipelines प्रदान करता है जो आपको अपने स्पाइडर में ऐसे फ़ंक्शन लिखने देते हैं जो आपके डेटा को प्रोसेस कर सकें, जैसे डेटा वैलिडेट करना, हटाना और डेटाबेस में सेव करना। यह spider Contracts देता है ताकि आप अपने स्पाइडर्स की टेस्टिंग कर सकें और आपको deep crawlers बनाने की सुविधा भी देता है। यह retries, redirection आदि जैसे कई वेरिएबल्स मैनेज करने देता है।यदि प्रोजेक्ट में ज्यादा लॉजिक की आवश्यकता नहीं है, तो BeautifulSoup काम के लिए अच्छा है, लेकिन यदि आपको proxys, कुकीज़ मैनेजमेंट और डेटा पाइपलाइंस जैसी कस्टमाइज़ेशन चाहिए, तो Scrapy सबसे अच्छा विकल्प है।

जानकारी: Synchronous का अर्थ है कि नए काम को शुरू करने से पहले आपको पहले काम के खत्म होने का इंतज़ार करना होगा, जबकि Asynchronous का अर्थ है कि आप पिछले काम के खत्म होने से पहले अगले काम पर जा सकते हैं

सीखने के लिए यहाँ एक रोचक DataCamp का BeautifulSoup ट्यूटोरियल है।

Scrapy इंस्टॉलेशन

scrapy

Python 3.0 (और आगे) इंस्टॉल होने पर, यदि आप anaconda उपयोग कर रहे हैं, तो आप conda से scrapy इंस्टॉल कर सकते हैं। anaconda prompt में निम्न कमांड लिखें:

conda install -c conda-forge scrapy

anaconda इंस्टॉल करने के लिए, Mac और Windows के ये DataCamp ट्यूटोरियल देखें।

वैकल्पिक रूप से, आप Python Package Installer pip का उपयोग कर सकते हैं। यह Linux, Mac और Windows पर काम करता है:

pip install scrapy

Scrapy Shell

Scrapy एक वेब-क्रॉलिंग शेल भी देता है जिसे Scrapy Shell कहा जाता है, जिसे डेवलपर्स किसी साइट के व्यवहार पर अपनी परिकल्पनाओं का परीक्षण करने के लिए उपयोग कर सकते हैं। चलिए AliExpress ई-कॉमर्स वेबसाइट पर टैबलेट्स के वेब पेज को लेते हैं। आप Scrapy शेल का उपयोग करके देख सकते हैं कि वेब पेज क्या-क्या कॉम्पोनेन्ट्स लौटाता है और उन्हें अपनी आवश्यकताओं के अनुसार कैसे उपयोग किया जा सकता है।

कमांड लाइन खोलें और निम्न कमांड लिखें:

scrapy shell

यदि आप anaconda उपयोग कर रहे हैं, तो आप यह कमांड anaconda prompt में भी लिख सकते हैं। कमांड लाइन या anaconda prompt पर आपका आउटपुट कुछ इस प्रकार होगा:

run crawler

आपको Scrapy शेल में fetch कमांड का उपयोग कर वेब पेज पर क्रॉलर चलाना होगा। एक क्रॉलर या स्पाइडर वेबपेज से होकर उसके टेक्स्ट और मेटाडेटा को डाउनलोड करता है।

fetch(https://pt.aliexpress.com/category/201005406/special-store.html)

नोट: हमेशा URL को कोट्स में रखें, सिंगल और डबल दोनों कोट्स काम करते हैं

आउटपुट इस प्रकार होगा:

output

क्रॉलर एक response लौटाता है जिसे शेल पर view(response) कमांड से देखा जा सकता है:

view(response)

और वेब पेज डिफॉल्ट ब्राउज़र में खुल जाएगा।

web page

आप Scrapy शेल में निम्न कमांड से रॉ HTML स्क्रिप्ट देख सकते हैं:

print(response.text)

scrapy shell

आप वह स्क्रिप्ट देखेंगे जो वेबपेज जेनरेट कर रही है। यही कंटेंट तब भी होता है जब आप किसी वेबपेज के खाली क्षेत्र पर राइट-क्लिक कर view source या view page source चुनते हैं। चूंकि आपको पूरी स्क्रिप्ट में से केवल प्रासंगिक जानकारी चाहिए, इसलिए ब्राउज़र डेवलपर टूल्स का उपयोग कर आप आवश्यक एलिमेंट का निरीक्षण करेंगे। चलिए निम्न एलिमेंट लेते हैं:

  • टैबलेट का नाम
  • टैबलेट की कीमत
  • ऑर्डर्स की संख्या
  • स्टोर का नाम

जिस एलिमेंट को चाहिए, उस पर राइट-क्लिक करें और नीचे दिखाए अनुसार inspect पर क्लिक करें:

inspect

ब्राउज़र के डेवलपर टूल्स वेब स्क्रैपिंग में आपकी बहुत मदद करेंगे। आप देख सकते हैं कि यह <a> टैग है जिसमें class product है और टेक्स्ट में प्रोडक्ट का नाम है:

inspect

एक्स्ट्रैक्शन के लिए CSS सेलेक्टर्स का उपयोग

आप इसे एलिमेंट एट्रिब्यूट्स या क्लासेज जैसे css सेलेक्टर से निकाल सकते हैं। प्रोडक्ट नाम निकालने के लिए Scrapy शेल में निम्न लिखें:

response.css(".product::text").extract_first()

आउटपुट होगा:

output

extract_first() वह पहला एलिमेंट निकालता है जो css सेलेक्टर को संतुष्ट करता है। यदि आप सभी प्रोडक्ट नाम निकालना चाहते हैं तो extract() का उपयोग करें:

response.css(".product::text").extract()

extract product names

निम्न कोड प्रोडक्ट्स की प्राइस रेंज निकालेगा:

response.css(".value::text").extract()

extract product names

इसी तरह आप ऑर्डर्स की संख्या और स्टोर का नाम भी ट्राय कर सकते हैं।

एक्स्ट्रैक्शन के लिए XPath का उपयोग

XPath XML दस्तावेज़ में नोड्स चुनने के लिए एक क्वेरी भाषा है [7]। आप XPath का उपयोग कर XML दस्तावेज़ में नेविगेट कर सकते हैं। बैकएंड में, Scrapy HTML डॉक्यूमेंट आइटम्स पर नेविगेट करने के लिए Xpath का उपयोग करता है। आपने ऊपर जो CSS सेलेक्टर्स उपयोग किए थे, वे भी XPath में कन्वर्ट हो जाते हैं, लेकिन कई मामलों में CSS उपयोग करना बहुत आसान होता है। फिर भी, आपको जानना चाहिए कि Scrapy में XPath कैसे काम करता है।

अपने Scrapy शेल में जाएँ और पहले की तरह fetch(https://pt.aliexpress.com/category/201005406/special-store.html/) लिखें। निम्न कोड स्निपेट्स ट्राय करें [3]:

response.xpath('/html').extract()

यह <html> टैग के अंदर का सारा कोड दिखाएगा। / का अर्थ है नोड का डायरेक्ट चाइल्ड। यदि आप html टैग के नीचे के <div> टैग्स पाना चाहते हैं तो आप लिखेंगे [3]:

response.xpath('/html//div').extract()

XPath के लिए, आपको / और // के उपयोग को समझना होगा ताकि आप चाइल्ड और डीसेंडेंट नोड्स में नेविगेट कर सकें। यहाँ XPath Nodes पर एक सहायक ट्यूटोरियल है और कुछ उदाहरण ट्राय करने के लिए।

यदि आप सभी <div> टैग्स चाहते हैं, तो आप /html का उपयोग किए बिना नीचे ड्रिल करके कर सकते हैं [3]:

response.xpath("//div").extract()

आप एट्रिब्यूट्स और उनके मानों का उपयोग करके उन नोड्स को और फ़िल्टर कर सकते हैं, जिनसे आप शुरू करते हैं और अपनी वांछित नोड्स तक पहुँचते हैं। नीचे क्लासेज और उनके मानों का उपयोग करने का सिंटैक्स है।

response.xpath("//div[@class='quote']/span[@class='text']").extract()

response.xpath("//div[@class='quote']/span[@class='text']/text()").extract()

नोड्स के अंदर का सारा टेक्स्ट निकालने के लिए text() का उपयोग करें

निम्न HTML कोड पर विचार करें:

आप <a> टैग के अंदर का टेक्स्ट पाना चाहते हैं, जो <div> का चाइल्ड नोड है जिसकी क्लासेज site-notice-container container हैं—आप इसे इस प्रकार कर सकते हैं:

response.xpath('//div[@class="site-notice-container container"]/a[@class="notice-close"]/text()').extract()

text inside tag

Scrapy प्रोजेक्ट और कस्टम स्पाइडर बनाना

वेब स्क्रैपिंग का उपयोग आप एक एग्रीगेटर बनाने के लिए कर सकते हैं, जिससे आप डेटा की तुलना कर सकें। उदाहरण के लिए, आप एक टैबलेट खरीदना चाहते हैं और प्रोडक्ट्स व कीमतों की तुलना साथ में करना चाहते हैं, तो आप अपनी वांछित पेजेज को क्रॉल कर सकते हैं और उन्हें एक Excel फाइल में स्टोर कर सकते हैं। यहाँ आप aliexpress.com से टैबलेट्स की जानकारी स्क्रैप करेंगे।

अब, आप उसी पेज के लिए एक कस्टम स्पाइडर बनाएँगे। सबसे पहले, आपको एक Scrapy प्रोजेक्ट बनाना होगा जिसमें आपका कोड और परिणाम स्टोर होंगे। कमांड लाइन या anaconda prompt में निम्न कमांड लिखें।

scrapy startproject aliexpress

scrapy project

यह आपके डिफॉल्ट python या anaconda इंस्टॉलेशन में एक हिडन फोल्डर बना देगा। aliexpress फोल्डर का नाम होगा। आप कोई भी नाम दे सकते हैं। आप एक्सप्लोरर से सीधे फोल्डर की सामग्री देख सकते हैं। फोल्डर की संरचना निम्न है:

folder names
फाइल/फोल्डरउद्देश्य
scrapy.cfgडिप्लॉय कॉन्फ़िगरेशन फाइल
aliexpress/प्रोजेक्ट का Python मॉड्यूल, आप अपना कोड यहीं से इम्पोर्ट करेंगे
__init.py__Initialization फाइल
items.pyप्रोजेक्ट आइटम्स फाइल
pipelines.pyप्रोजेक्ट पाइपलाइंस फाइल
settings.pyप्रोजेक्ट सेटिंग्स फाइल
spiders/वह डायरेक्टरी जहाँ आप बाद में अपने स्पाइडर्स रखेंगे
__init.py__Initialization फाइल

प्रोजेक्ट बन जाने के बाद आप नए बने डायरेक्टरी में जाएँगे और निम्न कमांड लिखेंगे:

[scrapy genspider aliexpress_tablets](https://pt.aliexpress.com/category/201005406/special-store.html)

command

यह spiders डायरेक्टरी में aliexpress_tablets.py नाम की एक टेम्पलेट फाइल बनाता है जैसा ऊपर चर्चा हुई। उस फाइल में कोड इस प्रकार है:

import scrapy

class AliexpressTabletsSpider(scrapy.Spider):
    name = 'aliexpress_tablets'
    allowed_domains = ['aliexpress.com']
    start_urls = ['https://www.aliexpress.com/category/200216607/tablets.html']


    def parse(self, response):
         pass

ऊपर के कोड में आप name, allowed_domains, sstart_urls और एक parse फ़ंक्शन देख सकते हैं।

  • name: स्पाइडर का नाम। उपयुक्त नाम आपको बनाए गए सभी स्पाइडर्स का ट्रैक रखने में मदद करेंगे। नाम यूनिक होने चाहिए, क्योंकि scrapy crawl name_of_spider चलाते समय इन्हीं का उपयोग होगा।
  • allowed_domains (वैकल्पिक): एक वैकल्पिक python लिस्ट, जिसमें वे डोमेन होते हैं जिन्हें क्रॉल करने की अनुमति है। इस लिस्ट में न होने वाले URLs के लिए रिक्वेस्ट क्रॉल नहीं की जाएगी। इसमें केवल वेबसाइट का डोमेन (उदाहरण: aliexpress.com) होना चाहिए, start_urls में दिए पूरे URL नहीं, अन्यथा आपको वार्निंग्स मिलेंगी।
  • start_urls: यह उल्लेखित URLs के लिए रिक्वेस्ट करता है। जब कोई खास URLs निर्दिष्ट न हों तो स्पाइडर इन्हीं URLs से क्रॉल शुरू करेगा [4]। तो सबसे पहले डाउनलोड होने वाले पेज वही होंगे जो यहाँ सूचीबद्ध हैं। बाद की रिक्वेस्ट्स start URLs में मौजूद डेटा से क्रमशः जेनरेट होंगी [4]।
  • parse(self, response): यह फ़ंक्शन तब कॉल होता है जब कोई URL सफलतापूर्वक क्रॉल हो जाता है। इसे callback फ़ंक्शन भी कहते हैं। क्रॉलिंग के परिणामस्वरूप मिलने वाला response (जिसका उपयोग Scrapy शेल में किया) इस फ़ंक्शन में पास होता है, और आप इसके अंदर एक्स्ट्रैक्शन कोड लिखते हैं!

जानकारी: आप Scrapy स्पाइडर के parse() फ़ंक्शन के अंदर HTML डॉक्यूमेंट को पार्स करने के लिए BeautifulSoup का उपयोग कर सकते हैं।

नोट: आप css सेलेक्टर्स के ज़रिए response.css() का उपयोग करके डेटा निकाल सकते हैं जैसा कि scrapy शेल सेक्शन में चर्चा हुई, और साथ ही XPath (XML) का उपयोग भी कर सकते हैं जो आपको चाइल्ड एलिमेंट्स तक पहुंचने देता है। आप pass() फ़ंक्शन में एडिट किए गए कोड में response.xpath() का उदाहरण देखेंगे।

आप aliexpress_tablet.py फाइल में बदलाव करेंगे। मैंने start_urls में एक और URL जोड़ा है। आप pass() फ़ंक्शन में नीचे दिखाए अनुसार एक्स्ट्रैक्शन लॉजिक जोड़ सकते हैं:

# -*- coding: utf-8 -*-
import scrapy


class AliexpressTabletsSpider(scrapy.Spider):
    name = 'aliexpress_tablets'
    allowed_domains = ['aliexpress.com']
    start_urls = ['https://www.aliexpress.com/category/200216607/tablets.html',
                 'https://www.aliexpress.com/category/200216607/tablets/2.html?site=glo&g=y&tag=']


    def parse(self, response):

        print("procesing:"+response.url)
        #Extract data using css selectors
        product_name=response.css('.product::text').extract()
        price_range=response.css('.value::text').extract()
        #Extract data using xpath
        orders=response.xpath("//em[@title='Total Orders']/text()").extract()
        company_name=response.xpath("//a[@class='store $p4pLog']/text()").extract()

        row_data=zip(product_name,price_range,orders,company_name)

        #Making extracted data row wise
        for item in row_data:
            #create a dictionary to store the scraped info
            scraped_info = {
                #key:value
                'page':response.url,
                'product_name' : item[0], #item[0] means product in the list and so on, index tells what value to assign
                'price_range' : item[1],
                'orders' : item[2],
                'company_name' : item[3],
            }

            #yield or give the scraped info to scrapy
            yield scraped_info

जानकारी: zip() n संख्या में iterables लेता है और tuples की एक लिस्ट लौटाता है। ट्यूपल का ith एलिमेंट हर iterable के ith एलिमेंट से बनता है। [8]

yield कीवर्ड का उपयोग तब किया जाता है जब आप एक generator फ़ंक्शन परिभाषित कर रहे होते हैं। जनरेटर फ़ंक्शन सामान्य फ़ंक्शन जैसा ही होता है, बस यह return की जगह yield का उपयोग करता है। जब कॉलर फ़ंक्शन को किसी मान की ज़रूरत होती है, तब yield उपयोग किया जाता है, और yield वाला फ़ंक्शन अपना लोकल स्टेट बनाए रखता है और मान देने के बाद वहीं से आगे निष्पादन जारी करता है। यहाँ yield जेनरेटेड डिक्शनरी Scrapy को देता है जो उसे प्रोसेस कर सेव करेगा!

अब आप स्पाइडर चला सकते हैं:

scrapy crawl aliexpress_tablets

आप कमांड लाइन पर नीचे जैसा लंबा आउटपुट देखेंगे:

command
command

डेटा एक्सपोर्ट करना

आपको डेटा CSV या JSON के रूप में चाहिए होगा ताकि आप उसे आगे विश्लेषण के लिए उपयोग कर सकें। इस ट्यूटोरियल का यह भाग बताएगा कि आप इस डेटा के लिए CSV और JSON फाइल कैसे सेव कर सकते हैं।

CSV फाइल सेव करने के लिए, प्रोजेक्ट डायरेक्टरी से settings.py खोलें और निम्न लाइनें जोड़ें:

FEED_FORMAT="csv"
FEED_URI="aliexpress.csv"

settings.py सेव करने के बाद, अपने प्रोजेक्ट डायरेक्टरी में फिर से scrapy crawl aliexpress_tablets चलाएँ।

project directory

CSV फाइल कुछ ऐसी दिखेगी:

csv file

नोट: हर बार जब आप स्पाइडर चलाते हैं, यह फाइल में जोड़ता जाएगा।

  • FEED_FORMAT [5]: यह उस फॉर्मैट को सेट करता है जिसमें आप डेटा स्टोर करना चाहते हैं। समर्थित फॉर्मैट्स हैं:
         + JSON
         + CSV
         + JSON Lines
         + XML
    
  • FEED_URI [5]: यह फाइल का लोकेशन देता है। आप फाइल को अपने लोकल स्टोरेज या FTP पर भी स्टोर कर सकते हैं।

Scrapy का Feed Export आपके फाइल नाम में टाइमस्टैम्प और स्पाइडर का नाम भी जोड़ सकता है, या आप इन्हें उस डायरेक्टरी की पहचान के लिए उपयोग कर सकते हैं जहाँ आप स्टोर करना चाहते हैं।

  • %(time)s: फीड बनाते समय इसे टाइमस्टैम्प से रिप्लेस किया जाता है [5]
  • %(name)s: इसे स्पाइडर नाम से रिप्लेस किया जाता है [5]

उदाहरण के लिए:

  • हर स्पाइडर के लिए एक डायरेक्टरी उपयोग करते हुए FTP में स्टोर करें [5]:

ftp://user:[email protected]/scraping/feeds/%(name)s/%(time)s.json

settings.py में किए गए Feed परिवर्तन प्रोजेक्ट के सभी स्पाइडर्स पर लागू होंगे। आप किसी विशेष स्पाइडर के लिए कस्टम सेटिंग्स भी सेट कर सकते हैं जो settings.py की सेटिंग्स को ओवरराइड कर देंगी।

# -*- coding: utf-8 -*-
import scrapy


class AliexpressTabletsSpider(scrapy.Spider):
    name = 'aliexpress_tablets'
    allowed_domains = ['aliexpress.com']
    start_urls = ['https://www.aliexpress.com/category/200216607/tablets.html',
                 'https://www.aliexpress.com/category/200216607/tablets/2.html?site=glo&g=y&tag=']

    custom_settings={ 'FEED_URI': "aliexpress_%(time)s.json",
                       'FEED_FORMAT': 'json'}

    def parse(self, response):

        print("procesing:"+response.url)
        #Extract data using css selectors
        product_name=response.css('.product::text').extract()
        price_range=response.css('.value::text').extract()
        #Extract data using xpath
        orders=response.xpath("//em[@title='Total Orders']/text()").extract()
        company_name=response.xpath("//a[@class='store $p4pLog']/text()").extract()

        row_data=zip(product_name,price_range,orders,company_name)

        #Making extracted data row wise
        for item in row_data:
            #create a dictionary to store the scraped info
            scraped_info = {
                #key:value
                'page':response.url,
                'product_name' : item[0], #item[0] means product in the list and so on, index tells what value to assign
                'price_range' : item[1],
                'orders' : item[2],
                'company_name' : item[3],
            }

            #yield or give the scraped info to Scrapy
            yield scraped_info

response.url उस पेज का URL लौटाता है जिससे response जेनरेट हुआ है। scrapy crawl aliexpress_tablets से क्रॉलर चलाने के बाद आप json फाइल देख सकते हैं:

json file

आपने ध्यान दिया होगा कि start_urls में दो लिंक्स हैं। दूसरी लिंक उसी टैबलेट्स सर्च रिज़ल्ट्स का पेज 2 है। सभी लिंक्स जोड़ना अव्यावहारिक हो जाएगा। एक क्रॉलर को स्वयं सभी पेजों से होकर क्रॉल करने में सक्षम होना चाहिए, और केवल शुरुआती बिंदु start_urls में दिया जाना चाहिए।

यदि किसी पेज के आगे और पेज हैं, तो उसके अंत में नेविगेटर दिखाई देगा जो पेजों के बीच आगे-पीछे जाने देगा। इस ट्यूटोरियल में जिस मामले को आप लागू कर रहे हैं, वह कुछ इस प्रकार दिखेगा:

inspect

आपको यह कोड दिखाई देगा:

code

जैसा कि आप देख सकते हैं, एक <span> टैग है जिसकी क्लास .ui-pagination-active है जो वर्तमान पेज दर्शाती है, और उसके नीचे सभी <a> टैग्स हैं जिनमें अगले पेज के लिंक्स हैं। हर बार आपको इस <span> टैग के बाद आने वाले <a> टैग्स लेने होंगे। यहाँ थोड़ा CSS काम आता है! इसमें आपको चाइल्ड नोड नहीं बल्कि sibling नोड चाहिए, इसलिए आपको ऐसा css सेलेक्टर बनाना होगा जो क्रॉलर को बताए कि .ui-pagination-active क्लास वाले <span> टैग के बाद आने वाले <a> टैग्स ढूँढे।

याद रखें! हर वेब पेज की अपनी संरचना होती है। वांछित एलिमेंट कैसे पाएँ, यह समझने के लिए आपको संरचना का थोड़ा अध्ययन करना होगा। कोड में लिखने से पहले हमेशा Scrapy Shell पर response.css(SELECTOR) ट्राय करें।

अपने aliexpress_tablets.py को नीचे दिए अनुसार संशोधित करें:


import scrapy


class AliexpressTabletsSpider(scrapy.Spider):
    name = 'aliexpress_tablets'
    allowed_domains = ['aliexpress.com']
    start_urls = ['https://www.aliexpress.com/category/200216607/tablets.html']


    custom_settings={ 'FEED_URI': "aliexpress_%(time)s.csv",
                       'FEED_FORMAT': 'csv'}

    def parse(self, response):

        print("procesing:"+response.url)
        #Extract data using css selectors
        product_name=response.css('.product::text').extract()
        price_range=response.css('.value::text').extract()
        #Extract data using xpath
        orders=response.xpath("//em[@title='Total Orders']/text()").extract()
        company_name=response.xpath("//a[@class='store $p4pLog']/text()").extract()

        row_data=zip(product_name,price_range,orders,company_name)

        #Making extracted data row wise
        for item in row_data:
            #create a dictionary to store the scraped info
            scraped_info = {
                #key:value
                'page':response.url,
                'product_name' : item[0], #item[0] means product in the list and so on, index tells what value to assign
                'price_range' : item[1],
                'orders' : item[2],
                'company_name' : item[3],
            }

            #yield or give the scraped info to scrapy
            yield scraped_info


            NEXT_PAGE_SELECTOR = '.ui-pagination-active + a::attr(href)'
            next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()
            if next_page:
                yield scrapy.Request(
                response.urljoin(next_page),
                callback=self.parse)

ऊपर के कोड में:

  • आपने पहले next_page = response.css(NEXT_PAGE_SELECTOR).extract_first() से अगले पेज का लिंक निकाला और फिर यदि next_page वेरिएबल को लिंक मिला और वह खाली नहीं है, तो यह if बॉडी में प्रवेश करेगा।

  • response.urljoin(next_page): parse() मेथड इसका उपयोग करके एक नया URL बनाएगा और एक नई रिक्वेस्ट देगा, जिसे बाद में callback को भेजा जाएगा। [9]

  • नया URL मिलने के बाद, यह उस लिंक को स्क्रैप करेगा, for बॉडी को निष्पादित करेगा और फिर अगले पेज को ढूँढेगा। यह तब तक चलता रहेगा जब तक अगला पेज लिंक नहीं मिल जाता।

यहाँ आप आराम से बैठकर अपने स्पाइडर को सभी पेज स्क्रैप करते हुए देख सकते हैं। ऊपर दिया स्पाइडर सभी अगले पेजों से एक्स्ट्रैक्ट करेगा। यह बहुत अधिक स्क्रैपिंग होगी! लेकिन आपका स्पाइडर इसे कर देगा! नीचे आप देख सकते हैं कि फाइल का साइज 1.1MB तक पहुँच गया है।

jupyter file

Scrapy आपके लिए कर देता है!

इस ट्यूटोरियल में, आपने Scrapy, उसका BeautifulSoup से तुलना, Scrapy Shell, और Scrapy में अपने स्पाइडर्स लिखना सीखा। Scrapy आपके लिए भारी-भरकम कोडिंग का काम संभाल लेता है—प्रोजेक्ट फाइल्स और फोल्डर्स बनाने से लेकर डुप्लिकेट URLs हैंडल करने तक—यह आपको कुछ ही मिनटों में हाई-पावर वेब स्क्रैपिंग करने देता है और सभी सामान्य डेटा फॉर्मैट्स के लिए सपोर्ट देता है जिन्हें आप अन्य प्रोग्राम्स में आगे इनपुट कर सकते हैं। यह ट्यूटोरियल निश्चित रूप से आपको Scrapy और उसके फ्रेमवर्क को समझने और उससे क्या-क्या किया जा सकता है, इसमें मदद करेगा। Scrapy में माहिर बनने के लिए इसकी सभी शानदार क्षमताओं से होकर गुजरना होगा, लेकिन इस ट्यूटोरियल ने आपको वेब पेजों के समूह को कुशलतापूर्वक स्क्रैप करने में सक्षम बना दिया है।

अधिक पढ़ने के लिए, आधिकारिक Scrapy डॉक्यूमेंटेशन देखें।

साथ ही, DataCamp का Web Scraping with Python कोर्स देखना न भूलें।

संदर्भ

विषय