2012-12-19 14 views
14

PhantomJSBeautifulSoup के विकल्प का उपयोग किया जा सकता है?phantomjs के साथ लिंक कैसे स्क्रैप करें

मैं एटीसी पर खोजने और टर्म में सभी लिंक पर जाने की कोशिश कर रहा हूं। पायथन में, मुझे पता है कि यह कैसे करें (सुंदर सूप के साथ) लेकिन आज मैं देखना चाहता हूं कि मैं फैंटॉमजेएस के साथ ऐसा कर सकता हूं या नहीं। मैं बहुत दूर नहीं जा रहा हूँ।

इस स्क्रिप्ट को एटीसी पर "हैलो किट्टी" खोजना चाहिए और सभी उत्पादों को <a class="listing-thumb" href=...></a> वापस करना चाहिए और उन्हें कंसोल में प्रिंट करना चाहिए। आदर्श रूप में मैं उन्हें बाद में देखूंगा और मुझे जो जानकारी चाहिए उसे प्राप्त करें। अभी यह सिर्फ जम जाता है। कोई विचार?

var page = require('webpage').create(); 
var url = 'http://www.etsy.com/search?q=hello%20kitty'; 

page.open(url, function(status){ 
    // list all the a.href links in the hello kitty etsy page 
    var link = page.evaluate(function() { 
     return document.querySelectorAll('a.listing-thumb'); 
    }); 
    for(var i = 0; i < link.length; i++){ console.log(link[i].href); } 
    phantom.exit(); 
}); 

मैं CasperJS है, जो बेहतर इस बात के लिए तैयार किया जा सकता है का उपयोग कर के साथ toyed है।

+1

मैं [cheerio] (https://github.com/MatthewMueller/cheerio) की जांच करने की सलाह देता हूं। यह वेब पेजों को स्क्रैप करने के कार्य के लिए बिल्कुल उपयुक्त है, और इसके ट्रैवर्सल/मैनिपुलेशन एपीआई jQuery के समान ही हैं। – davidchambers

उत्तर

4

आपके कोड के साथ एकमात्र समस्या यह है कि आप phantomjs scopes को समझ नहीं पाते हैं। आपके पास प्रेत और पेज स्कॉप्स हैं। आपने पेज स्कोप (पेज.एवलुएट रन पेज स्कोप) से मुख्य स्कोप तक जावास्क्रिप्ट डीओएम ऑब्जेक्ट रेफरेंस (जिन्हें धारावाहिक नहीं किया जा सकता) वापस करने का प्रयास किया। मुझे लगता है कि यह संभव नहीं है। यहाँ कोड है कि काम करता है इस प्रकार है:

var page = require('webpage').create(); 
var url = 'http://www.etsy.com/search?q=hello%20kitty'; 

// for debug (to see if page returns status code 200) 
page.onResourceReceived = function(response) { 
    if (response.url === url) { 
     console.log('Resorce: "' + response.url + '" status: ' + response.status); 

     if (response.status === 200) { 
      console.log(response.url); 
      for (var i = 0; i < response.headers.length; i++) { 
       console.log(response.headers[i].name + ': ' + response.headers[i].value); 
      } 
     } 
    } 
}; 

page.onLoadFinished = function(status){ 
    console.log('Status: ' + status); 

    console.log('Starting evaluate...'); 
    var links = page.evaluate(function() { 
     var nodes = [], 
      matches = document.querySelectorAll("a.listing-thumb"); 

      for(var i = 0; i < matches.length; ++i) { 
       nodes.push(matches[i].href); 
      } 

      return nodes; 
    }); 
    console.log('Done evaluate... count: ' + links.length); 

    if (links && links.length > 0) { 
     for(var i = 0; i < links.length; ++i) { 
      console.log('(' + i + ') ' + links[i]); 
     } 
    } else { 
     console.log("No match found!"); 
    } 

    phantom.exit(0); 
}; 

page.open(url); 
35

PhantomJS evaluate() को क्रमानुसार नहीं कर सकते और HTMLElements या NodeLists की तरह जटिल वस्तुओं लौटने के लिए, तो तुम से पहले serializable बातें करने के लिए उन्हें मैप करने के लिए है:

var page = require('webpage').create(); 
var url = 'http://www.etsy.com/search?q=hello%20kitty'; 

page.open(url, function(status) { 
    // list all the a.href links in the hello kitty etsy page 
    var links = page.evaluate(function() { 
     return [].map.call(document.querySelectorAll('a.listing-thumb'), function(link) { 
      return link.getAttribute('href'); 
     }); 
    }); 
    console.log(links.join('\n')); 
    phantom.exit(); 
}); 

नोट: यहाँ हम [].map.call() का उपयोग मानक Array के रूप में NodeList का इलाज करने के लिए।

+7

+1 इच्छा यह दस्तावेज़ों में स्पष्ट रूप से कहा गया था। नए रूप में, इस जवाब को खोजने में मुझे घंटों लग गए हैं! :-( – Alberto

+2

उहम्म ... क्या आपका मतलब है "कैस्परजेएस प्रलेखन आरेख में" * मूल प्रकार * * तीर या फ़ैंटॉमजेएस दस्तावेज़ में नोट "* तर्क और मूल्यांकन कार्य में वापसी मूल्य एक साधारण आदिम वस्तु होना चाहिए। [...] * "(नोट: कैस्परजेएस में लिंक [WebPage.evaluate] (https://github.com/ariya/phantomjs/wiki/API- संदर्भ- वेबपृष्ठ http://wwwevaluatefunction-arg1-arg2--object) गलत है)? मुझे यकीन है कि मुझे कुछ याद आ रहा है, क्योंकि आरेख में लिपि आसानी से निगरानी की जाती है, और नौसिखिया के रूप में मैंने सोचा कि मैं फैंटॉमजेएस दस्तावेज़ के बिना कर सकता हूं। वैसे भी इस शानदार टूल के लिए धन्यवाद। – Alberto

+0

हां, तो सरल, अभी तक दस्तावेज़ों में कहीं भी नहीं। बहुत बहुत धन्यवाद। – HartleySan

1

यहां कुछ कोड है जो मैंने हाल ही में लिखा है कि फ़ैंटॉमजे का उपयोग करके स्क्रैप यूआरएल, यदि आप केवल एक यूआरएल प्रदान करते हैं तो यह पृष्ठ पर सभी यूआरएलएस प्रदर्शित करेगा, अगर आप class|id का तर्क देते हैं तो इसके बाद "कक्षा/आईडी नाम" केवल कक्षा/आईडी के यूआरएल प्रदर्शित करें।

////////////////////////////////////////////////////////// 
///// PhantomJS URL Scraper v.1.3 ///// 
// 
// Copyrighted by +A.M.Danischewski 2016+ (c) 
// This program may be reutilized without limits, provided this 
// notice remain intact. 
// 
// Usage: phantomjs phantom_urls.js <URL> [["class"|"id"] [<query id/class name>]] 
// 
// Argument 1: URL -- "https://www.youtube.com/watch?v=8TniRMwL2Vg" 
// Argument 2: "class" or "id" 
// Argument 3: If Argument 2 was provided, "class name" or "id name" 
// 
// By default this program will display ALL urls from a user supplied URL. 
// If a class name or id name is provided then only URL's from the class 
// or id are displayed. 
// 
/////////////////////////////////// 

var page = require('webpage').create(), 
    system = require('system'), 
    address; 

if (system.args.length === 1) { 
    console.log(' Usage: phantomjs phantom_urls.js <URL> [["class"|"id"] [<query id/class name>]]'); 
    phantom.exit(); 
} 

address = system.args[1]; 
querytype= system.args[2]; 
queryclass = system.args[3]; 
page.open(address, function(status) { 
    if (status !== 'success') { 
    console.log('Error loading address: '+address); 
    } else { 
    //console.log('Success! In loading address: '+address); 
    } 
}); 

page.onConsoleMessage = function(msg) { 
    console.log(msg); 
} 

page.onLoadFinished = function(status) { 
    var dynclass="function() { window.class_urls = new Array(); window.class_urls_next=0; var listings = document.getElementsByClassName('"+queryclass+"'); for (var i=0; i < listings.length; i++) { var el = listings[i]; var ellnks=[].map.call(el.querySelectorAll('a'),function(link) {return link.getAttribute('href');}); var elhtml=el.innerHTML; window.class_urls.push(ellnks.join('\\n')); }; return window.class_urls;}"; 
    var dynid="function() { window.id_urls = new Array(); window.id_urls_next=0; var listings = document.getElementById('"+queryclass+"'); var ellnks=[].map.call(listings.querySelectorAll('a'),function(link) {return link.getAttribute('href');}); var elhtml=listings.innerHTML; window.id_urls.push(ellnks.join('\\n')); return window.id_urls;}"; 
    var allurls="function() { var links = page.evaluate(function() { return [].map.call(document.querySelectorAll('a'), function(link) { return link.getAttribute('href'); };); };); console.log(links.join('\\n')); }"; 
    var page_eval_function=""; 
    if (querytype === "class") { 
    console.log(page.evaluate(dynclass).toString().replace(/,/g, "\n")); 
    } else if (querytype === "id") { 
    console.log(page.evaluate(dynid).toString().replace(/,/g, "\n")); 
    } else { 
    var links = page.evaluate(function() { 
     return [].map.call(document.querySelectorAll('a'), function(link) { 
      return link.getAttribute('href'); 
     }); 
    });  
     console.log(links.join('\n')); 
    }    
    phantom.exit(); 
}; 
संबंधित मुद्दे