2012-08-31 10 views
8

मुझे एक पृष्ठ के मौजूदा शैलियों (शायद इनलाइन) के साथ HTML प्राप्त करने की आवश्यकता है जो सर्वर पक्ष का उपयोग करके प्रतिपादन समाप्त हो जाती है और चलती स्क्रिप्ट समाप्त करती है आवेदन जो केवल एक यूआरएल दिया जाएगा (कुकीज, कोई पोस्ट नहीं, कोई प्रजनन फॉर्म इत्यादि जैसी कोई अतिरिक्त जानकारी नहीं)।एक पृष्ठ के मौजूदा शैलियों (शायद रेखांकित) के साथ एचटीएमएल प्राप्त करें जो चलने वाली स्क्रिप्ट को समाप्त करने और समाप्त होने वाली स्क्रिप्ट

ब्राउज़र लाइब्रेरी का उपयोग कर अस्थायी रूप से चल रहे ब्राउज़र या स्टैंड स्टैंड अकेलेपन के लिए एक पुल/प्रॉक्सी एक स्वीकार्य समाधान है (हालांकि, चयनित ब्राउज़र या ब्राउज़र लाइब्रेरी सभी प्रमुख प्लेटफ़ॉर्म पर उपलब्ध होना चाहिए, और बिना चलाने में सक्षम होना चाहिए एक ओएस जीयूआई उपस्थिति स्थापित या स्थापित)।

बाद में सभी स्क्रिप्ट को हटाने के लिए एक वैकल्पिक आवश्यकता है (इसके लिए पहले से अकेले समाधान खड़े हैं, इसे यहां जोड़ना क्योंकि शायद दिया गया उत्तर प्रतिपादन करते समय स्क्रिप्ट को हटाने में सक्षम होगा)।

मैं एचटीएमएल + सीएसएस में एचटीएमएल + सीएसएस में एक मौजूदा एचटीएमएल दस्तावेज़ की मौजूदा एचटीएमएल दस्तावेज़ में एक स्नैपशॉट कैसे प्राप्त करूं (वर्तमान में रेखांकित) और वर्तमान छवियों (data URI का उपयोग कर)?

यदि यह शुद्ध PHP का उपयोग करके किया जा सकता है तो यह एक प्लस होगा (हालांकि मुझे शक है, मुझे कुछ भी दिलचस्प नहीं मिला है)।

संपादित करें: मुझे पता है कि HTTP संसाधन लोड और एक यूआरएल के लिए HTML पाने के लिए, जो वह नहीं है कि मैं क्या तलाश कर रहा हूँ;)

संपादित 2 उदाहरण इनपुट HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
    <head> 
     <title></title> 

     <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 

     <link rel="stylesheet" type="text/css" href="/css/example.css"> 
     <script type="text/javascript" src="/javascript/example.js"></script> 

     <script type="text/javascript"> 
      window.addEventListener("load", 
       function(event){ 
        document.title="New title"; 

        document.getElementById("pic_0").style.border="0px"; 
       } 
      ); 
     </script> 
     <style type="text/css"> 
      p{ 
       color: blue; 
      } 
     </style> 
    </head> 
    <body> 
     <p>Hello world!</p> 
     <p> 
      <img 
       alt="" 
       style="border: 1px" 
       id="pic_0" 
       src="http://linuxgazette.net/144/misc/john/helloworld.png" 
      > 
     </p> 
    </body> 
</html> 

उदाहरण आउटपुट:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
    <head> 
     <title>New title</title> 

     <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 

     <style type="text/css"> 
      b{font-weight: bold} 
     </style> 

     <style type="text/css"> 
      p{ 
       color: blue; 
      } 
     </style> 
    </head> 
    <body> 
     <p>Hello world!</p> 
     <p> 
      <img 
       alt="" 
       style="border: 0px" 
       id="pic_0" 
       src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoBAMAAAB+0KVeAAAAK3RFWHRDcmVhdGlvbiBUaW1lAFYgMzEgYXVnLiAyMDEyIDE3OjU4OjU1ICswMjAwWMdbPwAAAAd0SU1FB9wIHw8ABeoUyU4AAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAEZ0FNQQAAsY8L/GEFAAAABlBMVEX///8AAABVwtN+AAAAXklEQVR42uWQUQ6AMAhD6Q3a+19WqsawwMf+NLEfy3iDlC7idTGQp/YglFAsUMqSwjlQOhN3mIMTHDq70SeEWBbt0EG8POWkDySvmCh/SssvNfwIfb+hFmgjFKPf6gDQBAQ368m09AAAAABJRU5ErkJggg==" 
      > 
     </p> 
    </body> 
</html> 

सूचना कैसे +०१२३६४५८४२०टैग बदल गया, border: 1pxborder: 0px बन गया, कैसे छवि यूआरएल data URI में परिवर्तित किया गया था।

उदाहरण के लिए, इनमें से कुछ परिवर्तन (इनलाइन सीएसएस और <title> टैग) Google क्रोम इंस्पेक्टर का उपयोग करते हुए दस्तावेज़ का निरीक्षण करते समय देखा जा सकता है।

संपादित करें 3: ऑन-पेज वाले (शैलियों और छवियों) के साथ बाहरी संसाधनों को बदलने और जावास्क्रिप्ट को हटाने का एक आसान हिस्सा है। हार्ड भाग जावास्क्रिप्ट चलाने के बाद सीएसएस शैली की गणना कर रहा है।

संपादित करें 4 शायद यह इंजेक्शन जावास्क्रिप्ट का उपयोग करके किया जा सकता है (फिर भी ब्राउज़र नियंत्रण की आवश्यकता है)?

+2

आप एक प्रतिपादन इंजन को [जैसे बाइंडिंग की जरूरत है वेबकिट] - यह एक अच्छी शुरुआत हो सकती है: http://stackoverflow.com/questions/4362855/php-read-an-http-url-and-write-it-to-pdf – moonwave99

+0

@ moonwave99 हाँ मुझे wkhtmltopdf के बारे में पता है:) अगर यह शुरुआत है तो मेरे पास बहुत काम है ... :( –

+0

वैसे मुझे लगता है कि पीडीएफ को प्रतिपादन एक प्लस है - कोड में शुद्ध एचटीएमएल + सीएसएस प्राप्त करने पर एक कदम होना चाहिए, यदि आप की हिम्मत है लाइब्रेरी में गोता लगाने के लिए आपको आवश्यक डेटा मिल सकता है ^^ – moonwave99

उत्तर

6

PhantomJS जावास्क्रिप्ट एपीआई के साथ एक हेडलेस (जीयूआई-कम) वेबकिट है। यह मेरे सभी प्रश्नों पर अनुरोध करता है, जैसा कि मैंने अपने प्रश्न में अनुरोध किया था।

यह जीयूआई-कम वेब ब्राउज़र को नियंत्रित करने के लिए जावास्क्रिप्ट स्क्रिप्ट चला सकता है। इसमें एक शक्तिशाली एपीआई है, और बहुत सारे और उदाहरण हैं।

पिछले 2-3 दिनों में मेरे खाली समय में मैंने अपने प्रश्न का समाधान लिखा, और इसमें सभी आवश्यकताओं को खूबसूरती से शामिल किया गया। मुझे एक वेबपृष्ठ नहीं मिला है जिसके लिए यह काम नहीं करेगा।

प्रयोग, कमांड लाइन:

phantomjs save_as_html.js http://stackoverflow.com/q/12215844/584490 saved.html 

अन्य सभी लोड होने के बाद जावास्क्रिप्ट को n सेकंड के लिए चलाने की अनुमति है, इसे जावास्क्रिप्ट द्वारा पूरी तरह से उत्पन्न वेब पृष्ठों के लिए भी काम करना चाहिए।

नोट्स:

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

  • <link> और <img> टैग अपने स्थान पर रखा जाता है, और data: यूआरआई href अंदर उपयोग किया जाता है और src URL के बजाय क्रमशः गुण,। background-image के लिए भी यही सच है, जिसे सभी DOM नोड्स पर getComputedStyle() का उपयोग करके पढ़ा जाता है।

  • <script> टैग और ईवेंट हैंडलर गुण हटा दिए जाते हैं।

  • <link>rel="alternative" के साथ टैग भी हटा दिए गए हैं (शायद वे नहीं होना चाहिए, और इसके बजाय यदि संबंधित हो तो एक पूर्ण यूआरएल में तय किया जाना चाहिए)।

  • वर्तमान में संभाला नहीं गया है, और इसकी स्रोत विशेषता about:blank पर सेट की जा रही है।

सभी क्रॉस साइट स्क्रिप्टिंग सुरक्षा प्रतिबंधों से सावधान रहें, ताकि सभी संसाधनों को लोड किया जा सके। सुनिश्चित करें कि आप अपने फेसबुक खाते के कुछ गुप्त प्रमाण-पत्रों का उपयोग करते समय दुर्भावनापूर्ण वेबपृष्ठों को सहेजने का प्रयास नहीं करते :)।

save_as_html.js सामग्री:

//http://stackoverflow.com/a/12256190/584490 

var page = require('webpage').create(); 
page.onConsoleMessage = function (msg) { console.log(msg); }; 

var system = require('system'); 
var address, output, size; 


if (system.args.length!=3) 
{ 
    console.log('Usage: save_as_html.js URL filename'); 
    phantom.exit(1); 
} 
else 
{ 
    address = system.args[1]; 
    output = system.args[2]; 

    page.viewportSize = {  
     width: 1680, 
     height: 1050, 
    }; 

    //SECURITY_ERR: DOM Exception 18: An attempt was made to break through the security policy of the user agent. 
    //Enable cross site scripting: 
    page.settings.XSSAuditingEnabled=false; 
    page.settings.localToRemoteUrlAccessEnabled=true; 
    page.settings.webSecurityEnabled=false; 

    page.settings.userAgent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"; 
    page.settings.ignoreSslErrors=true; 

    page.open(address, function (status){ 
     if (status!=='success') 
     { 
      console.log("Unable to load URL, returned status: "+status); 
      phantom.exit(1); 
     } 
     else 
     { 
      window.setTimeout(function(){ 
       page.evaluate(function(){ 
        var nodeList=document.getElementsByTagName("*"); 

        var arrEventHandlerAttributes=[ 
         "onblur", "onchange", "onclick", "ondblclick", "onfocus", "onkeydown", "onkeyup", "onkeypress", "onkeyup","onload", 
         "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onreset", "onselect", "onsubmit", "onunload" 
        ]; 


        //http://stackoverflow.com/a/7372816/584490 
        var base64Encode=function(str) 
        { 
         var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 
         var out = "", i = 0, len = str.length, c1, c2, c3; 
         while (i < len) { 
          c1 = str.charCodeAt(i++) & 0xff; 
          if (i == len) { 
           out += CHARS.charAt(c1 >> 2); 
           out += CHARS.charAt((c1 & 0x3) << 4); 
           out += "=="; 
           break; 
          } 
          c2 = str.charCodeAt(i++); 
          if (i == len) { 
           out += CHARS.charAt(c1 >> 2); 
           out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); 
           out += CHARS.charAt((c2 & 0xF) << 2); 
           out += "="; 
           break; 
          } 
          c3 = str.charCodeAt(i++); 
          out += CHARS.charAt(c1 >> 2); 
          out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); 
          out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); 
          out += CHARS.charAt(c3 & 0x3F); 
         } 
         return out; 
        }; 


        for(var n=nodeList.length-1; n>0; n--) 
        { 
         try 
         { 
          var el=nodeList[n]; 

          if(el.nodeName=="IMG" && el.src.substr(0, 5)!="data:") 
          { 
           /*var canvas=document.createElement("canvas"); 

           canvas.width=parseInt(el.width); 
           canvas.height=parseInt(el.height); 

           var ctx=canvas.getContext("2d"); 
           ctx.drawImage(el, 0, 0); 
           el.src=canvas.toDataURL();*/ 

           var xhr=new XMLHttpRequest(); 

           xhr.open(
            "get", 
            el.src, 
            /*Asynchronous*/ false 
           ); 

           xhr.overrideMimeType("text/plain; charset=x-user-defined"); 

           xhr.send(null); 

           var strResponseContentType=xhr.getResponseHeader("Content-type").split(";")[0].replace(/[^a-z0-9\/-]/gi, ""); 
           el.src="data:"+strResponseContentType+";base64,"+base64Encode(xhr.responseText); 
          } 
          else if(el.nodeName=="LINK") 
          { 
           if(el.rel=="alternate") 
           { 
            el.parentNode.removeChild(el); 
           } 
           else if(el.href.substr(0, 5)!="data:") 
           { 
            var xhr=new XMLHttpRequest(); 

            xhr.open(
             "get", 
             el.href, 
             /*Asynchronous*/ false 
            ); 

            xhr.overrideMimeType("text/plain; charset=x-user-defined"); 

            xhr.send(null); 

            //var strResponseContentType=xhr.getResponseHeader("Content-type").split(";")[0].replace(/[^a-z0-9\/-]/gi, ""); 
            //el.href="data:"+strResponseContentType+";base64,"+base64Encode(xhr.responseText); 
            el.href="data:"+el.type+";base64,"+base64Encode(xhr.responseText); 
           } 

           continue; 
          } 
          else if(el.nodeName=="SCRIPT") 
          { 
           el.parentNode.removeChild(el); 

           continue; 
          } 
          else if(el.nodeName=="IFRAME") 
          { 
           el.src="about:blank"; 

           continue; 
          } 

          for(var z=arrEventHandlerAttributes.length-1; z>=0; z--) 
           el.removeAttribute(arrEventHandlerAttributes[z]); 

          var strBackgroundImageURL=window.getComputedStyle(el).getPropertyValue("background-image").replace("/[\s]/g", ""); 
          if(strBackgroundImageURL.substr(0, 4)=="url(" && strBackgroundImageURL.substr(4, 5)!="data:") 
          { 
           strBackgroundImageURL=strBackgroundImageURL.substr(4, strBackgroundImageURL.length-5); 

           /*var imageTemp=document.createElement("img"); 
           imageTemp.src=strBackgroundImageURL; 

           imageTemp.onload=function(e){ 
            var canvas=document.createElement("canvas"); 

            canvas.width=parseInt(imageTemp.width); 
            canvas.height=parseInt(imageTemp.height); 

            var ctx=canvas.getContext("2d"); 
            ctx.drawImage(imageTemp, 0, 0); 
            el.style.backgroundImage="url("+canvas.toDataURL()+")"; 
           }; 

           if (imageTemp.complete) 
            imageTemp.onload(); 
           */ 

           var xhr=new XMLHttpRequest(); 

           xhr.open(
            "get", 
            strBackgroundImageURL, 
            /*Asynchronous*/ false 
           ); 

           xhr.overrideMimeType("text/plain; charset=x-user-defined"); 

           xhr.send(null); 

           var strResponseContentType=xhr.getResponseHeader("Content-type").split(";")[0].replace(/[^a-z0-9\/-]/gi, ""); 
           el.style.backgroundImage="url("+"data:"+strResponseContentType+";base64,"+base64Encode(xhr.responseText)+")"; 
          } 

          if(el.nodeName=="A") 
          { 
           el.href="#";//TODO convert relative paths to absolute ones (keep URLs); 
           el.setAttribute("onclick", "return false;");//TODO: remove this when the above is fixed. 
          } 
          else if(el.nodeName=="FORM") 
          { 
           el.setAttribute("action", ""); 
           el.setAttribute("onsubmit", "return false;"); 
          } 
         } 
         catch(error) 
         { 
          //what can be done about it? 
         } 
        } 
       }); 

       require("fs").write(output, page.content, "w"); 

       phantom.exit(); 
      }, 1000); 
     } 
    }); 
} 

+1

आप स्वयं निर्मित 'base64Encode' फ़ंक्शन के बजाय मूल' btoa' का उपयोग कर सकते हैं। – vbarbarosh

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

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