पिछली बार हमने एक बुनियादी वेब स्क्रैपर लागू किया था जिसने StackOverflow से नवीनतम प्रश्न डाउनलोड किए और परिणामों को MongoDB में संग्रहीत किया। इस लेख में हम अपने स्क्रैपर का विस्तार करेंगे ताकि यह प्रत्येक पृष्ठ के नीचे पृष्ठ पर अंक लगाना लिंक के माध्यम से क्रॉल करे और प्रत्येक पृष्ठ से प्रश्नों (प्रश्न शीर्षक और URL) को स्क्रैप कर दे।
निःशुल्क बोनस: पूर्ण स्रोत कोड के साथ Python + MongoDB प्रोजेक्ट कंकाल डाउनलोड करने के लिए यहां क्लिक करें जो आपको दिखाता है कि Python से MongoDB तक कैसे पहुंचें।
अपडेट:
- 09/06/2015 - स्क्रेपी (v1.0.3) और पाइमोंगो (v3.0.3) के नवीनतम संस्करण में अपडेट किया गया - चीयर्स!
किसी भी स्क्रैपिंग कार्य को शुरू करने से पहले, साइट की उपयोग की शर्तों की नीति की समीक्षा करें और robots.txt फ़ाइल का सम्मान करें। साथ ही, कम समय में कई अनुरोधों वाली साइट को न भरकर नैतिक स्क्रैपिंग प्रथाओं का पालन करें। आपके द्वारा स्क्रैप की गई किसी भी साइट के साथ ऐसा व्यवहार करें जैसे कि वह आपकी अपनी हो।
यह रियल पायथन और ग्योर्गी के लोगों के बीच एक सहयोग टुकड़ा है - एक पायथन उत्साही और सॉफ्टवेयर डेवलपर, वर्तमान में एक बड़ी डेटा कंपनी में काम कर रहा है और एक ही समय में एक नई नौकरी की तलाश कर रहा है। आप उनसे ट्विटर पर सवाल पूछ सकते हैं - @kissgyorgy.
आरंभ करना
जहां से हमने छोड़ा था, वहां से जारी रखने के दो संभावित तरीके हैं।
पहला यह है कि parse_item
में प्रतिक्रिया से प्रत्येक अगले पृष्ठ लिंक को निकालकर हमारे मौजूदा स्पाइडर का विस्तार किया जाए। एक xpath अभिव्यक्ति के साथ विधि और बस yield
एक Request
उसी parse_item
पर कॉलबैक के साथ ऑब्जेक्ट करें तरीका। इस तरह स्क्रैपी हमारे द्वारा निर्दिष्ट लिंक के लिए स्वचालित रूप से एक नया अनुरोध करेगा। आप इस विधि के बारे में अधिक जानकारी स्क्रेपी दस्तावेज़ में प्राप्त कर सकते हैं।
दूसरा, बहुत आसान विकल्प एक अलग प्रकार की मकड़ी का उपयोग करना है - CrawlSpider
(जोड़ना)। यह मूल Spider
. का विस्तारित संस्करण है , बिल्कुल हमारे उपयोग के मामले के लिए डिज़ाइन किया गया है।
क्रॉलस्पाइडर
हम पिछले ट्यूटोरियल से उसी स्क्रैपी प्रोजेक्ट का उपयोग करेंगे, इसलिए यदि आपको इसकी आवश्यकता हो तो रेपो से कोड प्राप्त करें।
बॉयलरप्लेट बनाएं
"स्टैक" निर्देशिका के भीतर, crawl
. से स्पाइडर बॉयलरप्लेट जनरेट करके प्रारंभ करें टेम्पलेट:
$ scrapy genspider stack_crawler stackoverflow.com -t crawl
Created spider 'stack_crawler' using template 'crawl' in module:
stack.spiders.stack_crawler
स्क्रैपी प्रोजेक्ट अब इस तरह दिखना चाहिए:
├── scrapy.cfg
└── stack
├── __init__.py
├── items.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
├── stack_crawler.py
└── stack_spider.py
और stack_crawler.py फ़ाइल इस तरह दिखनी चाहिए:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from stack.items import StackItem
class StackCrawlerSpider(CrawlSpider):
name = 'stack_crawler'
allowed_domains = ['stackoverflow.com']
start_urls = ['http://www.stackoverflow.com/']
rules = (
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
def parse_item(self, response):
i = StackItem()
#i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
#i['name'] = response.xpath('//div[@id="name"]').extract()
#i['description'] = response.xpath('//div[@id="description"]').extract()
return i
हमें बस इस बॉयलरप्लेट में कुछ अपडेट करने की जरूरत है…
अपडेट करें start_urls
सूची
सबसे पहले, प्रश्नों के पहले पृष्ठ को start_urls
. में जोड़ें सूची:
start_urls = [
'http://stackoverflow.com/questions?pagesize=50&sort=newest'
]
अपडेट करेंrules
सूची
इसके बाद, हमें rules
में रेगुलर एक्सप्रेशन जोड़कर मकड़ी को यह बताना होगा कि वह अगले पृष्ठ के लिंक कहां ढूंढ सकती है विशेषता:
rules = [
Rule(LinkExtractor(allow=r'questions\?page=[0-9]&sort=newest'),
callback='parse_item', follow=True)
]
स्क्रेपी अब स्वचालित रूप से उन लिंक के आधार पर नए पृष्ठों का अनुरोध करेगा और parse_item
को प्रतिक्रिया देगा प्रश्न और शीर्षक निकालने की विधि।
यदि आप बारीकी से ध्यान दे रहे हैं, तो यह रेगेक्स क्रॉलिंग को पहले 9 पृष्ठों तक सीमित कर देता है क्योंकि इस डेमो के लिए हम सभी को स्क्रैप नहीं करना चाहते हैं। 176,234 पृष्ठ!
अपडेट करें parse_item
विधि
अब हमें केवल यह लिखने की आवश्यकता है कि xpath के साथ पृष्ठों को कैसे पार्स किया जाए, जो हमने पिछले ट्यूटोरियल में पहले ही किया था - इसलिए बस इसे कॉपी करें:
def parse_item(self, response):
questions = response.xpath('//div[@class="summary"]/h3')
for question in questions:
item = StackItem()
item['url'] = question.xpath(
'a[@class="question-hyperlink"]/@href').extract()[0]
item['title'] = question.xpath(
'a[@class="question-hyperlink"]/text()').extract()[0]
yield item
मकड़ी के लिए बस इतना ही, लेकिन नहीं करें इसे अभी शुरू करें।
डाउनलोड विलंब जोड़ें
हमें settings.py में डाउनलोड विलंब सेट करके StackOverflow (और उस मामले के लिए किसी भी साइट) के लिए अच्छा होना चाहिए :
DOWNLOAD_DELAY = 5
यह स्क्रेपी को प्रत्येक नए अनुरोध के बीच कम से कम 5 सेकंड प्रतीक्षा करने के लिए कहता है। आप अनिवार्य रूप से खुद को सीमित कर रहे हैं। यदि आप ऐसा नहीं करते हैं, तो StackOverflow आपको सीमित कर देगा; और यदि आप दर सीमा लगाए बिना साइट को स्क्रैप करना जारी रखते हैं, तो आपके आईपी पते पर प्रतिबंध लगाया जा सकता है। तो, अच्छा बनें - किसी भी साइट को स्क्रैप करें जैसे कि वह आपकी अपनी हो।
अब केवल एक ही काम करना बाकी है - डेटा स्टोर करें।
मोंगोडीबी
पिछली बार हमने केवल 50 प्रश्न डाउनलोड किए थे, लेकिन चूंकि इस बार हम बहुत अधिक डेटा प्राप्त कर रहे हैं, इसलिए हम डेटाबेस में डुप्लिकेट प्रश्नों को जोड़ने से बचना चाहते हैं। हम एक MongoDB अप्सर्ट का उपयोग करके ऐसा कर सकते हैं, जिसका अर्थ है कि हम प्रश्न शीर्षक को अपडेट करते हैं यदि यह पहले से ही डेटाबेस में है और अन्यथा सम्मिलित करें।
MongoDBPipeline
को संशोधित करें हमने पहले परिभाषित किया था:
class MongoDBPipeline(object):
def __init__(self):
connection = pymongo.MongoClient(
settings['MONGODB_SERVER'],
settings['MONGODB_PORT']
)
db = connection[settings['MONGODB_DB']]
self.collection = db[settings['MONGODB_COLLECTION']]
def process_item(self, item, spider):
for data in item:
if not data:
raise DropItem("Missing data!")
self.collection.update({'url': item['url']}, dict(item), upsert=True)
log.msg("Question added to MongoDB database!",
level=log.DEBUG, spider=spider)
return item
<ब्लॉकक्वॉट> सादगी के लिए, हमने क्वेरी को ऑप्टिमाइज़ नहीं किया और इंडेक्स के साथ डील नहीं की क्योंकि यह प्रोडक्शन का माहौल नहीं है।
परीक्षा
मकड़ी शुरू करो!
$ scrapy crawl stack_crawler
अब वापस बैठें और अपने डेटाबेस को डेटा से भरते हुए देखें!
$ mongo
MongoDB shell version: 3.0.4
> use stackoverflow
switched to db stackoverflow
> db.questions.count()
447
>
निष्कर्ष
आप संपूर्ण स्रोत कोड को Github रिपॉजिटरी से डाउनलोड कर सकते हैं। प्रश्नों के साथ नीचे कमेंट करें। चीयर्स!
निःशुल्क बोनस: पूर्ण स्रोत कोड के साथ Python + MongoDB प्रोजेक्ट कंकाल डाउनलोड करने के लिए यहां क्लिक करें जो आपको दिखाता है कि Python से MongoDB तक कैसे पहुंचें।
<ब्लॉकक्वॉट>अधिक वेब स्क्रैपिंग की तलाश है? रियल पायथन पाठ्यक्रमों की जाँच करना सुनिश्चित करें। एक पेशेवर वेब स्क्रैपर किराए पर लेना चाहते हैं? GoScrape देखें।