2009-07-28 12 views
39

私が達成したいのは、どのWebサイトからもPythonでWebサイトのスクリーンショットを取得することです。Pythonを使用してウェブサイトのスクリーンショット/画像を取得するにはどうすればよいですか?

ENV:Linuxの

+4

このサイトをすばやく検索すると、これに多くの重複が生じます。ここでは良いスタートです:http://stackoverflow.com/questions/713938/how-can-i-generate-a-screenshot-of-a-webpage-using-a-server-side-script – Shog9

+0

Shog9:ありがとう!!あなたのリンクはいくつか持っています...それをチェックします。 –

+0

Shog9:答えとして追加してみませんか?それはあなたにポイントを与えることができます。 –

答えて

8

Macの場合はwebkit2png、Linux + KDEの場合はkhtml2pngを使用できます。私は前者を試しましたが、それはかなりうまく動作し、後者が使われることを聞いたことがあります。

私は最近、QtWebKitに出くわしました。これはクロスプラットフォーム(QtがWeb Kitをライブラリに巻き込んだと思います)。しかし、私はそれを試したことがないので、私はあなたにもっと多くを伝えることはできません。

QtWebKitリンクは、Pythonからのアクセス方法を示しています。あなたは少なくとも他の人と同じことをするためにサブプロセスを使用することができるはずです。

+0

khtml2pngはウェブサイトによって古くなっており、[python-webkit2png](https://github.com/adamn/python-webkit2png/)が推奨されています。 – sebix

0

はあなたが実行しているどのような環境では言及していない、HTMLをレンダリングすることができるのです純粋なPythonのWebブラウザがないので、大きな違いになります。

Macをお使いの場合は、webkit2pngを大変うれしく使っています。そうでない場合、他の人が指摘しているように、たくさんのオプションがあります。

5

私はarsの答えにコメントできませんが、実際にはQtWebkitを使用してRoland Tapken's codeを実行しています。

自分のブログに掲載されているRolandの投稿がUbuntuでうまくいっていることを確認したかっただけです。私たちの生産バージョンは、彼が書いたものを使用せずに終了しましたが、私たちはPyQt/QtWebKitバインディングを大いに活用しています。ここで

+0

Cool。私はそれが次回このようなものが必要なときに試してみるべきだと思う。 – ars

+0

RabbitMQサーバーの上にRabbitMQサーバーを配置し、Xvfbサーバーとその中で実行されているプロセスを制御して、スクリーンショットを構築するためのコードを構築しました。それは適度な速さで、許容される量のメモリ使用量で実行されます。 – aezell

38

は、WebKitのを使用して、簡単な解決策である:ここでは http://webscraping.com/blog/Webpage-screenshots-with-webkit/

import sys 
import time 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from PyQt4.QtWebKit import * 

class Screenshot(QWebView): 
    def __init__(self): 
     self.app = QApplication(sys.argv) 
     QWebView.__init__(self) 
     self._loaded = False 
     self.loadFinished.connect(self._loadFinished) 

    def capture(self, url, output_file): 
     self.load(QUrl(url)) 
     self.wait_load() 
     # set to webpage size 
     frame = self.page().mainFrame() 
     self.page().setViewportSize(frame.contentsSize()) 
     # render image 
     image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) 
     painter = QPainter(image) 
     frame.render(painter) 
     painter.end() 
     print 'saving', output_file 
     image.save(output_file) 

    def wait_load(self, delay=0): 
     # process app events until page loaded 
     while not self._loaded: 
      self.app.processEvents() 
      time.sleep(delay) 
     self._loaded = False 

    def _loadFinished(self, result): 
     self._loaded = True 

s = Screenshot() 
s.capture('http://webscraping.com', 'website.png') 
s.capture('http://webscraping.com/blog', 'blog.png') 
+0

よく機能します、ありがとうございます。ただし、コマンドラインから実行した場合にのみ、確実に動作します。 djangoプロジェクトでは、サブプロセスを使用します.Popen() –

+1

は、PythonのWebフレームワーク内で正常に動作します。しかし、Webkitがヘッドレスで動作するようにするには多少の努力が必要です。 – hoju

+2

誰かが@hojuのメソッドを使用する際に問題を経験しましたか?それはすべてのWebページで動作しません... – Hiatus

33

私のソリューションは、さまざまなソースからの助けをつかむことです。これは、完全なWebページの画面キャプチャを取ると、それをトリミング(オプション)とトリミングされた画像からサムネイルを生成します。

要件:

  1. がphantomjsをインストールするノードのパッケージマネージャを使用してNodeJS
  2. をインストールします(あなたがそれを使用している場合は、あなたのvirtualenvの中で)npm -g install phantomjs
  3. セレンをインストール
  4. インストール要件は次のとおりimageMagick
  5. システムパスにファントムを追加する(Windowsの場合)

import os 
from subprocess import Popen, PIPE 
from selenium import webdriver 

abspath = lambda *p: os.path.abspath(os.path.join(*p)) 
ROOT = abspath(os.path.dirname(__file__)) 


def execute_command(command): 
    result = Popen(command, shell=True, stdout=PIPE).stdout.read() 
    if len(result) > 0 and not result.isspace(): 
     raise Exception(result) 


def do_screen_capturing(url, screen_path, width, height): 
    print "Capturing screen.." 
    driver = webdriver.PhantomJS() 
    # it save service log file in same directory 
    # if you want to have log file stored else where 
    # initialize the webdriver.PhantomJS() as 
    # driver = webdriver.PhantomJS(service_log_path='/var/log/phantomjs/ghostdriver.log') 
    driver.set_script_timeout(30) 
    if width and height: 
     driver.set_window_size(width, height) 
    driver.get(url) 
    driver.save_screenshot(screen_path) 


def do_crop(params): 
    print "Croping captured image.." 
    command = [ 
     'convert', 
     params['screen_path'], 
     '-crop', '%sx%s+0+0' % (params['width'], params['height']), 
     params['crop_path'] 
    ] 
    execute_command(' '.join(command)) 


def do_thumbnail(params): 
    print "Generating thumbnail from croped captured image.." 
    command = [ 
     'convert', 
     params['crop_path'], 
     '-filter', 'Lanczos', 
     '-thumbnail', '%sx%s' % (params['width'], params['height']), 
     params['thumbnail_path'] 
    ] 
    execute_command(' '.join(command)) 


def get_screen_shot(**kwargs): 
    url = kwargs['url'] 
    width = int(kwargs.get('width', 1024)) # screen width to capture 
    height = int(kwargs.get('height', 768)) # screen height to capture 
    filename = kwargs.get('filename', 'screen.png') # file name e.g. screen.png 
    path = kwargs.get('path', ROOT) # directory path to store screen 

    crop = kwargs.get('crop', False) # crop the captured screen 
    crop_width = int(kwargs.get('crop_width', width)) # the width of crop screen 
    crop_height = int(kwargs.get('crop_height', height)) # the height of crop screen 
    crop_replace = kwargs.get('crop_replace', False) # does crop image replace original screen capture? 

    thumbnail = kwargs.get('thumbnail', False) # generate thumbnail from screen, requires crop=True 
    thumbnail_width = int(kwargs.get('thumbnail_width', width)) # the width of thumbnail 
    thumbnail_height = int(kwargs.get('thumbnail_height', height)) # the height of thumbnail 
    thumbnail_replace = kwargs.get('thumbnail_replace', False) # does thumbnail image replace crop image? 

    screen_path = abspath(path, filename) 
    crop_path = thumbnail_path = screen_path 

    if thumbnail and not crop: 
     raise Exception, 'Thumnail generation requires crop image, set crop=True' 

    do_screen_capturing(url, screen_path, width, height) 

    if crop: 
     if not crop_replace: 
      crop_path = abspath(path, 'crop_'+filename) 
     params = { 
      'width': crop_width, 'height': crop_height, 
      'crop_path': crop_path, 'screen_path': screen_path} 
     do_crop(params) 

     if thumbnail: 
      if not thumbnail_replace: 
       thumbnail_path = abspath(path, 'thumbnail_'+filename) 
      params = { 
       'width': thumbnail_width, 'height': thumbnail_height, 
       'thumbnail_path': thumbnail_path, 'crop_path': crop_path} 
      do_thumbnail(params) 
    return screen_path, crop_path, thumbnail_path 


if __name__ == '__main__': 
    ''' 
     Requirements: 
     Install NodeJS 
     Using Node's package manager install phantomjs: npm -g install phantomjs 
     install selenium (in your virtualenv, if you are using that) 
     install imageMagick 
     add phantomjs to system path (on windows) 
    ''' 

    url = 'http://stackoverflow.com/questions/1197172/how-can-i-take-a-screenshot-image-of-a-website-using-python' 
    screen_path, crop_path, thumbnail_path = get_screen_shot(
     url=url, filename='sof.png', 
     crop=True, crop_replace=False, 
     thumbnail=True, thumbnail_replace=False, 
     thumbnail_width=200, thumbnail_height=150, 
    ) 

これらは、生成された画像です:

+0

完全に私のDjangoビューで動作します。デフォルトのユーザーエージェントを設定する必要はなく、画面の解像度のみを設定します。 – serfer2

+0

ウェブページにアクセスするための証明書が必要な場合はどうなりますか? –

+2

質問はNodeJSではなく、Pythonに関するものでした。 –

-1

はこれを試してみてください。..

#!/usr/bin/env python 

import gtk.gdk 

import time 

import random 

while 1 : 
    # generate a random time between 120 and 300 sec 
    random_time = random.randrange(120,300) 

    # wait between 120 and 300 seconds (or between 2 and 5 minutes) 
    print "Next picture in: %.2f minutes" % (float(random_time)/60) 

    time.sleep(random_time) 

    w = gtk.gdk.get_default_root_window() 
    sz = w.get_size() 

    print "The size of the window is %d x %d" % sz 

    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1]) 
    pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1]) 

    ts = time.time() 
    filename = "screenshot" 
    filename += str(ts) 
    filename += ".png" 

    if (pb != None): 
     pb.save(filename,"png") 
     print "Screenshot saved to "+filename 
    else: 
     print "Unable to get the screenshot." 
関連する問題