गतिशील पृष्ठ के लिए स्क्रैप के साथ सेलेनियम


85

मैं एक वेबपेज से उत्पाद जानकारी को स्क्रैप करने के लिए उपयोग करने की कोशिश कर रहा हूं। इस तरह दिखता है मेरा-टू-स्क्रेप्ड वेबपेज:

  • 10 उत्पादों के साथ एक product_list पृष्ठ से शुरू होता है
  • "अगला" बटन पर क्लिक करने से अगले 10 उत्पाद लोड हो जाते हैं (दो पृष्ठों के बीच यूआरएल नहीं बदलता है)
  • मैं उत्पाद पृष्ठ में प्रत्येक उत्पाद लिंक का पालन करने के लिए LinkExtractor का उपयोग करता हूं, और मुझे आवश्यक सभी जानकारी मिलती है

मैंने अगले बटन-अजाक्स-कॉल को दोहराने की कोशिश की, लेकिन काम नहीं कर पाया, इसलिए मैं सेलेनियम दे रहा हूं। मैं सेलेनियम के वेबड्राइवर को एक अलग स्क्रिप्ट में चला सकता हूं, लेकिन मुझे नहीं पता कि कैसे स्क्रैपी के साथ एकीकृत किया जाए। मैं अपने छींटे मकड़ी में सेलेनियम का हिस्सा कहाँ रखूँगा?

मेरा मकड़ी बहुत मानक है, निम्न की तरह:

class ProductSpider(CrawlSpider):
    name = "product_spider"
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/shanghai']
    rules = [
        Rule(SgmlLinkExtractor(restrict_xpaths='//div[@id="productList"]//dl[@class="t2"]//dt'), callback='parse_product'),
        ]

    def parse_product(self, response):
        self.log("parsing product %s" %response.url, level=INFO)
        hxs = HtmlXPathSelector(response)
        # actual data follows

किसी भी विचार की सराहना की है। धन्यवाद!


जवाबों:


123

यह वास्तव में इस बात पर निर्भर करता है कि आपको साइट को कैसे परिमार्जन करने की आवश्यकता है और आप कैसे और क्या डेटा प्राप्त करना चाहते हैं।

यहाँ एक उदाहरण है कि कैसे आप का उपयोग कर ebay पर पृष्ठांकन का पालन कर सकते है Scrapy+ Selenium:

import scrapy
from selenium import webdriver

class ProductSpider(scrapy.Spider):
    name = "product_spider"
    allowed_domains = ['ebay.com']
    start_urls = ['http://www.ebay.com/sch/i.html?_odkw=books&_osacat=0&_trksid=p2045573.m570.l1313.TR0.TRC0.Xpython&_nkw=python&_sacat=0&_from=R40']

    def __init__(self):
        self.driver = webdriver.Firefox()

    def parse(self, response):
        self.driver.get(response.url)

        while True:
            next = self.driver.find_element_by_xpath('//td[@class="pagn-next"]/a')

            try:
                next.click()

                # get the data and write it to scrapy items
            except:
                break

        self.driver.close()

यहाँ "सेलेनियम मकड़ियों" के कुछ उदाहरण दिए गए हैं:


के Seleniumसाथ उपयोग करने के लिए एक विकल्प भी है Scrapy। कुछ मामलों में, ScrapyJSमिडलवेयर का उपयोग करना पृष्ठ के गतिशील भागों को संभालने के लिए पर्याप्त है। नमूना वास्तविक दुनिया का उपयोग:


आपकी सहायता के लिए धन्यवाद। वास्तव में मेरी सबसे बड़ी समस्या अगले के बाद के हिस्से में है (क्लिक करें)। हर बार मुझे एक नया पेज मिलता है, लेकिन क्या मैं अभी भी एक LinkExtractor का उपयोग करके सभी उत्पाद यूआरएल निकाल सकता हूं और फिर उन्हें पार्स करने के लिए कॉलबैक का उपयोग कर सकता हूं?
Z. लिन

2
क्या पुन: उपयोग करने का एक तरीका है जो पहले से ही उपयोग किए जाने के बजाय स्क्रैप द्वारा पकड़ा गया है self.driver.get(response.url)?
ईथर

2
@ हेलसीऑनअब्राहम रायरेज, यह सिर्फ़ एक हिस्सा है, जिसमें सेलेनियम हिस्सा होता है। सेलेनियम होने के बाद, आमतौर पर self.driver.page_sourceHTML को पार्स करने के लिए चयनकर्ता उदाहरण में पास किया जाता है, आइटम इंस्टेंस को बनाते हैं, उन्हें पाइपलाइनों को पास करते हैं या, अतिरिक्त अनुरोध करने के लिए सेलेनियम कुकीज़ को पार्स किया जा सकता है और पास किया जा सकता है। लेकिन, अगर आपको स्क्रैपी फ्रेमवर्क आर्किटेक्चर की शक्ति की आवश्यकता नहीं है, तो, निश्चित रूप से, आप सिर्फ सेलेनियम का उपयोग कर सकते हैं - यह स्वयं तत्वों को खोजने में काफी शक्तिशाली है।
एलेक्सी

4
@alecxe हाँ, जबकि मैं अवधारणा प्राप्त करता हूं। Im अभी भी उस हिस्से में उलझन में है जहां आप सेलेनियम का उपयोग करके पृष्ठ स्रोत को निकालते हैं और उन तत्वों को पास करते हैं जिन्हें आप स्क्रैप करना चाहते हैं। उदाहरण के लिए। एक लोड अधिक बटन है जिस पर क्लिक करने पर अधिक आइटम दिखाई देंगे, लेकिन आप उन वस्तुओं के लिए xpath निकालें। अब आप कैसे स्क्रैप करने के लिए उन xpaths पास करते हैं? क्योंकि केवल उन वस्तुओं को दिखाया गया है जब आपने पहली बार पृष्ठ का अनुरोध किया था कि वे खिन्न हो जाएंगे और सेलेनियम के साथ लोड अधिक बटन पर क्लिक करने के बाद नहीं
हैल्सी अब्राहम रामिरेज़

2
@HalcyonAbrahamRamirez को मिला, मैं और आइटम तब तक लोड करूंगा जब तक कि जोड़ने के लिए और कुछ न हो। फिर, driver.page_sourceइसे ले जाएं और इसे पास करें Selector()..
alecxe

2

यदि (url दो पृष्ठों के बीच नहीं बदलता है) तो आपको NOT_filter को जोड़ना चाहिए = True with your scrapy.Request () या scrapy इस url को पहले पेज की प्रोसेसिंग के बाद डुप्लिकेट के रूप में मिलेगा।

यदि आपको जावास्क्रिप्ट के साथ पृष्ठों को प्रस्तुत करने की आवश्यकता है , तो आपको स्क्रेपी-स्प्लैश का उपयोग करना चाहिए , आप इस स्क्रैप मिडलवेयर की भी जांच कर सकते हैं जो सेलेनियम का उपयोग करके जावास्क्रिप्ट पृष्ठों को संभाल सकते हैं या आप ऐसा कर सकते हैं कि किसी भी हेडलेस ब्राउज़र को लॉन्च करके

लेकिन अधिक प्रभावी और तेज समाधान आपके ब्राउज़र का निरीक्षण करता है और देखता है कि फॉर्म सबमिट करने या किसी निश्चित घटना को ट्रिगर करने के दौरान क्या अनुरोध किए जाते हैं। अपने ब्राउज़र द्वारा भेजे गए अनुरोधों के समान अनुकरण करने का प्रयास करें। यदि आप अनुरोध (ओं) को सही ढंग से दोहरा सकते हैं, तो आपको आवश्यक डेटा मिलेगा।

यहाँ एक उदाहरण है :

class ScrollScraper(Spider):
    name = "scrollingscraper"

    quote_url = "http://quotes.toscrape.com/api/quotes?page="
    start_urls = [quote_url + "1"]

    def parse(self, response):
        quote_item = QuoteItem()
        print response.body
        data = json.loads(response.body)
        for item in data.get('quotes', []):
            quote_item["author"] = item.get('author', {}).get('name')
            quote_item['quote'] = item.get('text')
            quote_item['tags'] = item.get('tags')
            yield quote_item

        if data['has_next']:
            next_page = data['page'] + 1
            yield Request(self.quote_url + str(next_page))

जब पेजिंग url हर पेज के लिए समान है और POST अनुरोध का उपयोग करता है तो आप उपयोग कर सकते हैं scrapy.FormRequest () के बजाय scrapy.Request () का , दोनों समान हैं लेकिन FormRequest एक नया तर्क ( formdata = ) जोड़ता है निर्माता के लिए)।

यहाँ एक और मकड़ी का उदाहरण इस पोस्ट का रूप है :

class SpiderClass(scrapy.Spider):
    # spider name and all
    name = 'ajax'
    page_incr = 1
    start_urls = ['http://www.pcguia.pt/category/reviews/#paginated=1']
    pagination_url = 'http://www.pcguia.pt/wp-content/themes/flavor/functions/ajax.php'

    def parse(self, response):

        sel = Selector(response)

        if self.page_incr > 1:
            json_data = json.loads(response.body)
            sel = Selector(text=json_data.get('content', ''))

        # your code here

        # pagination code starts here
        if sel.xpath('//div[@class="panel-wrapper"]'):
            self.page_incr += 1
            formdata = {
                'sorter': 'recent',
                'location': 'main loop',
                'loop': 'main loop',
                'action': 'sort',
                'view': 'grid',
                'columns': '3',
                'paginated': str(self.page_incr),
                'currentquery[category_name]': 'reviews'
            }
            yield FormRequest(url=self.pagination_url, formdata=formdata, callback=self.parse)
        else:
            return
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.