PHP

2012-02-10 6 views
7

का उपयोग कर समानांतर में पृष्ठों को डाउनलोड करना मुझे एक ऐसी वेबसाइट स्क्रैप करना है जहां मुझे एकाधिक यूआरएल लाने की आवश्यकता है और फिर उन्हें एक-एक करके संसाधित करना होगा। वर्तमान प्रक्रिया कुछ हद तक इस तरह जाती है।PHP

मैं एक बेस यूआरएल लाता हूं और इस पृष्ठ से सभी माध्यमिक यूआरएल प्राप्त करता हूं, फिर प्रत्येक माध्यमिक यूआरएल के लिए मैं उस यूआरएल को प्राप्त करता हूं, प्रक्रिया पाता हूं, कुछ तस्वीरें डाउनलोड करता हूं (जो काफी लंबा समय लेता है) और इस डेटा को डेटाबेस में स्टोर करता है, फिर अगला यूआरएल लाएं और प्रक्रिया दोहराएं।

इस प्रक्रिया में, मुझे लगता है कि मैं प्रत्येक पुनरावृत्ति की शुरुआत में माध्यमिक यूआरएल लाने में कुछ समय बर्बाद कर रहा हूं। इसलिए मैं पहले पुनरावृत्ति को संसाधित करते समय समानांतर में अगले यूआरएल लाने की कोशिश कर रहा हूं।

मुख्य प्रक्रिया से एक PHP स्क्रिप्ट को कॉल करने के लिए, मेरे दिमाग में समाधान है, जो डाउनलोडर कहता है, जो सभी यूआरएल डाउनलोड करेगा (curl_multi या wget के साथ) और उन्हें कुछ डेटाबेस में स्टोर करें।

मेरे सवालों का

  • कैसे कॉल करने के लिए इस तरह के downloder एसिंक्रोनस रूप, मैं नहीं चाहता कि मेरी मुख्य स्क्रिप्ट तक downloder पूरा करता इंतजार करना चाहते हैं।
  • साझा किए गए डेटा जैसे साझा किए गए डेटा को स्टोर करने के लिए कोई भी स्थान। बेशक, डेटाबेस के अलावा।
  • भंडारण और पुनर्प्राप्ति के दौरान डेटा भ्रष्ट हो जाता है, इस से बचने के लिए कोई संभावना नहीं है?
  • इसके अलावा, कृपया मुझे बताएं कि किसी के पास बेहतर योजना है या नहीं।
+2

PHP वास्तव में कई प्रक्रियाओं को लॉन्च करने के लिए डिज़ाइन नहीं किया गया है। इसे पूरा करने के लिए पाइथन जैसी भाषा क्यों न देखें? – afuzzyllama

+0

@afuzzyllama यह सिर्फ एक उप मॉड्यूल है, पूरी परियोजना PHP –

+0

[nodejs] (http://nodejs.org) में है इसके लिए यह सही होगा। – Xeoncross

उत्तर

6

जब मैं सुनता हूं कि कोई curl_multi_exec का उपयोग करता है तो आमतौर पर यह पता चला है कि वे इसे 100 यूआरएल के साथ लोड करते हैं, फिर पूरा होने पर प्रतीक्षा करें, और फिर उन सभी को संसाधित करें, और फिर अगले 100 यूआरएल के साथ शुरू करें ... दोष मैं, मैं भी ऐसा कर रहा था, लेकिन फिर मुझे पता चला कि कुछ अभी भी प्रगति पर है, जबकि curl_multi को हैंडल को हटाना/जोड़ना संभव है, और यह वास्तव में बहुत समय बचाता है, खासकर अगर आप पहले से ही खुले कनेक्शन का उपयोग करते हैं। मैंने कॉलबैक के अनुरोधों की कतार संभालने के लिए एक छोटी पुस्तकालय लिखी; मैं निश्चित रूप से यहाँ पूर्ण संस्करण पोस्टिंग नहीं कर रहा हूँ ("छोटे" अभी भी काफी कोड का एक सा है), लेकिन यहाँ आप सामान्य विचार देने के लिए मुख्य बात का एक सरलीकृत संस्करण है:

public function launch() { 
    $channels = $freeChannels = array_fill(0, $this->maxConnections, NULL); 
    $activeJobs = array(); 
    $running = 0; 
    do { 
     // pick jobs for free channels: 
     while (!(empty($freeChannels) || empty($this->jobQueue))) { 
      // take free channel, (re)init curl handle and let 
      // queued object set options 
      $chId = key($freeChannels); 
      if (empty($channels[$chId])) { 
       $channels[$chId] = curl_init(); 
      } 
      $job = array_pop($this->jobQueue); 
      $job->init($channels[$chId]); 
      curl_multi_add_handle($this->master, $channels[$chId]); 
      $activeJobs[$chId] = $job; 
      unset($freeChannels[$chId]); 
     } 
     $pending = count($activeJobs); 

     // launch them: 
     if ($pending > 0) { 
      while(($mrc = curl_multi_exec($this->master, $running)) == CURLM_CALL_MULTI_PERFORM); 
       // poke it while it wants 
      curl_multi_select($this->master); 
       // wait for some activity, don't eat CPU 
      while ($running < $pending && ($info = curl_multi_info_read($this->master))) { 
       // some connection(s) finished, locate that job and run response handler: 
       $pending--; 
       $chId = array_search($info['handle'], $channels); 
       $content = curl_multi_getcontent($channels[$chId]); 
       curl_multi_remove_handle($this->master, $channels[$chId]); 
       $freeChannels[$chId] = NULL; 
        // free up this channel 
       if (!array_key_exists($chId, $activeJobs)) { 
        // impossible, but... 
        continue; 
       } 
       $activeJobs[$chId]->onComplete($content); 
       unset($activeJobs[$chId]); 
      } 
     } 
    } while (($running > 0 && $mrc == CURLM_OK) || !empty($this->jobQueue)); 
} 

मेरी संस्करण $ में नौकरियां वास्तव में अलग वर्ग के हैं, न कि नियंत्रकों या मॉडल के उदाहरण। वे बस सेटिंग कर्ल विकल्प को संभालने, प्रतिक्रिया को पार्स करने और कॉम्प्लेट पर दिए गए कॉलबैक को कॉल करते हैं। इस संरचना के साथ पूल के कुछ खत्म होने के तुरंत बाद नए अनुरोध शुरू हो जाएंगे।

बेशक यह वास्तव में आपको बचाता नहीं है अगर न केवल समय निकालने पर प्रसंस्करण होता है बल्कि प्रसंस्करण भी ... और यह एक वास्तविक समांतर हैंडलिंग नहीं है। लेकिन मुझे अभी भी उम्मीद है कि यह मदद करता है। :)

पीएस मेरे लिए एक चाल है। :) एक बार 8 घंटे की नौकरी अब 50 कनेक्शन के पूल का उपयोग करके 3-4 मिनट में पूर्ण हो जाती है। उस भावना का वर्णन नहीं कर सकता। :) मैंने वास्तव में योजनाबद्ध रूप से काम करने की उम्मीद नहीं की थी, क्योंकि PHP के साथ यह शायद ही कभी काम करता है ... यह ठीक है, उम्मीद है कि यह कम से कम एक घंटे में खत्म हो जाएगा ... Wha ... रुको .. पहले से ही ?! 8-ओ "

+0

साझा करने के लिए धन्यवाद, अगर आप जिथब खोजते हैं तो आप इस तरह के अन्य पुस्तकालय भी पा सकते हैं। – Xeoncross

+0

वास्तव में उपयोगी उत्तर, लेकिन आपकी टिप्पणी ने मुझे बहुत मदद की, धन्यवाद आदमी ... –

+0

आपका स्वागत है। :) मुझे लगता है कि मैंने इसे उत्तर में रखा होगा ... – Slava

2

आप curl_multi उपयोग कर सकते हैं: http://www.somacon.com/p537.php

आप भी इस ग्राहक के पक्ष कर रहे हैं और जावास्क्रिप्ट का उपयोग कर विचार कर सकते हैं।


एक अन्य समाधान तो यह समानांतर काम करता है और एक JSON सारणी रिटर्न इसके पूरा होने के बाद, एक शिकारी/संग्राहक कि आप करने के लिए यूआरएल की एक सरणी प्रस्तुत लिखने के लिए है।

एक और तरीका रखें: यदि आपके पास 100 यूआरएल थे तो आप mysite.tld/huntergatherer पर उस सरणी (शायद JSON के रूप में भी) पोस्ट कर सकते हैं - जो कुछ भी आप चाहते हैं वह जो कुछ भी चाहता है वह करता है और बस JSON लौटाता है।

+0

ये, मैं पहले से ही curl_multi usin हूँ, जावास्क्रिप्ट अच्छा लगता है, क्या मुझे कुछ और विवरण मिल सकता है? –

0

PHP, पायथन-पिकुरल स्क्रिप्ट से निष्पादित करने का प्रयास करें। PHP कर्ल से आसान, तेज।

2

कर्ल बहु समाधान के अलावा, किसी अन्य व्यक्ति के पास gearman workers का बैच है। यदि आप इस मार्ग पर जाते हैं, तो मुझे supervisord डीमॉन श्रमिकों के भार को शुरू करने का एक अच्छा तरीका मिला है।

+0

धन्यवाद! पहले इस विस्तार के बारे में कभी नहीं सुना है। – Slava

1

चीजें आप इसके अलावा में पर गौर करना चाहिए बहु कर्ल करने के लिए:

  • गैर अवरुद्ध धाराओं (उदाहरण: PHP-MIO)
  • ZeroMQ कई श्रमिकों ऐसा अनुरोध अतुल्यकालिक रूप से

जबकि बंद को उत्पन्न करने के लिए node.js, ruby ​​EventMachine या इसी तरह के उपकरण इस सामान को करने के लिए बहुत बढ़िया हैं, जिन चीजों का मैंने उल्लेख किया है, वे PHP में भी काफी आसान बनाते हैं।

+0

गैर-अवरुद्ध धाराएं वास्तव में एक अच्छी पढ़ाई है, क्षमा करें, लेकिन मैं केवल एक ही उत्तर का चयन कर सकता हूं। धन्यवाद –

संबंधित मुद्दे