2013-06-04 21 views
19

È possibile utilizzare il rendering di PhantomJS's in PDF quando PhantomJS viene utilizzato in combinazione con Selenium e Python? (es. mimare il comportamento di page.render('file.pdf') all'interno di Python tramite Selenium).Python + Selenium + PhantomJS render to PDF

Mi rendo conto che questo utilizza GhostDriver e GhostDriver in realtà non supporta molto in termini di stampa.

Se è possibile un'altra alternativa che non è il selenio, sono tutto orecchie.

+0

Hai guardato Pypdf2? http://www.blog.pythonlibrary.org/tag/python-pdf-series/ – Amit

+0

@Amit: piuttosto estesamente, dato che lo uso sempre. Anche Phaseit ha detto che "PyPDF2 non ha conoscenza dell'HTML". Non renderizza in modo affidabile alcun HTML. – Rejected

+0

@ Respinto, è necessario che lo screenshot si verifichi in uno stato esatto durante il test? O stai solo cercando di caricare una pagina e renderizzare in PDF? –

risposta

1

È possibile utilizzare selenium.selenium.capture_screenshot('file.png') ma questo vi darà una schermata come png non un pdf. Non sembra essere un modo per ottenere uno screenshot come pdf.

Ecco la documentazione per capture_screenshot: http://selenium.googlecode.com/git/docs/api/py/selenium/selenium.selenium.html?highlight=screenshot#selenium.selenium.selenium.capture_screenshot

+1

Il PDF è un fattore chiave. Non riesco a passare a un'immagine semplice per una moltitudine di motivi, ad esempio ricerca di testo, moduli, media incorporati, ecc. – Rejected

1

provato pdfkit? Può eseguire il rendering di file PDF da pagine html.

+0

Ho esaminato anche questo. PDFKit converte HTML -> PDF, ma non ha ulteriori funzionalità. L'analisi del contenuto per determinare se una pagina contiene il contenuto desiderato prima che il PDF sia tristemente non è possibile. – Rejected

+0

Sì, sto avendo gli stessi problemi con PDFKit, vorrei un rendering più avanzato, usarlo con un framework JS è piuttosto complicato .. :( – moodh

+0

"Analisi del contenuto per determinare se una pagina contiene il contenuto desiderato" - > Beh, non puoi fare tu stesso l'analisi del contenuto e se è uguale allora basta inviarlo per renderizzare con pdfkit. Ecco come lo farei io. – Jonathan

0

@rejected, lo so che non è menzionato che vogliono utilizzare sottoprocessi, ma ...

Si può effettivamente essere in grado di sfruttare la comunicazione sottoprocesso di più di quanto previsto. In teoria, è possibile prendere Ariya's stdin/stdout example ed estenderlo per essere uno script wrapper relativamente generico. Potrebbe prima accettare una pagina da caricare, quindi ascoltare (& esecuzione) le azioni di test su quella pagina. Alla fine, si potrebbe dare il via alla .render o anche fare una cattura generico per la gestione degli errori:

try { 
    // load page & execute stdin commands 
} catch (e) { 
    page.render(page + '-error-state.pdf'); 
} 
+0

L'esecuzione del codice ricevuto tramite stdin dovrebbe essere eseguita tramite 'eval', e dalle mie esperienze di provare a farlo, è sia inse cura e inaffidabile. A meno che non mi sbagli? – Rejected

+0

Mentre vorresti essere cauto con il tuo input (dal punto di vista dell'affidabilità), probabilmente non dovresti preoccuparti della sicurezza poiché (presumo) tu possiedi il processo. –

+0

È anche possibile white-list di comandi specifici, ecc. Per tiri più veloci in caso di errori imprevisti. Tuttavia, lo scenario migliore che immaginerei è che estrai i tuoi test (o altra logica) che potrebbero verificarsi prima dell'acquisizione dello schermo in un file .js separato e caricali nella pagina (http://phantomjs.org/api/phantom/ metodo/iniettare-js.html). Potresti fare in modo che Python passi al massimo un arg per caricare il file specifico JS. –

8

Ecco una soluzione che utilizza il selenio e il comando speciale per GhostDriver (dovrebbe funzionare dal GhostDriver 1.1.0 e PhantomJS 1.9. 6, testati con PhantomJS 1.9.8):

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

"""Download a webpage as a PDF.""" 


from selenium import webdriver 


def download(driver, target_path): 
    """Download the currently displayed page to target_path.""" 
    def execute(script, args): 
     driver.execute('executePhantomScript', 
         {'script': script, 'args': args}) 

    # hack while the python interface lags 
    driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute') 
    # set page format 
    # inside the execution script, webpage is "this" 
    page_format = 'this.paperSize = {format: "A4", orientation: "portrait" };' 
    execute(page_format, []) 

    # render current page 
    render = '''this.render("{}")'''.format(target_path) 
    execute(render, []) 


if __name__ == '__main__': 
    driver = webdriver.PhantomJS('phantomjs') 
    driver.get('http://stackoverflow.com') 
    download(driver, "save_me.pdf") 

vedere anche la mia risposta alla stessa domanda here.