質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

2622閲覧

ヘッダー固定のキャプチャをきれいに撮りたい

jin007

総合スコア34

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2019/04/11 03:46

編集2019/04/11 04:58

実現したい事

seleniumを使ってヘッダーが固定されているサイトのキャプチャをきれいに撮れるようにしたい

現状

ヘッダーが固定されていて邪魔。
イメージ説明

環境

selenium 2.45.0
Java 1.8
Chrome 73.0.3683.103

参考サイト

こちら

現在のソース

Java

1WebDriver driver = new ChromeDriver(); 2 driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); 3 driver.get(baseUrl + "/sample.html"); 4 driver.switchTo().defaultContent(); 5 TakesScreenshot ts = (TakesScreenshot) new Augmenter().augment(driver); 6 7 //JS実行用のExecuter 8 JavascriptExecutor jexec = (JavascriptExecutor) driver; 9 10 //画面サイズで必要なものを取得 11 int innerH = Integer.parseInt(String.valueOf(jexec.executeScript("return window.innerHeight"))); 12 int innerW =Integer.parseInt(String.valueOf(jexec.executeScript("return window.innerWidth"))); 13 int scrollH = Integer.parseInt(String.valueOf(jexec.executeScript("return document.documentElement.scrollHeight"))); 14 15 //イメージを扱うための準備 16 BufferedImage img = new BufferedImage(innerW, scrollH, BufferedImage.TYPE_INT_ARGB); 17 Graphics g = img.getGraphics(); 18 19 //スクロールを行うかの判定 20 if(innerH>scrollH){ 21 BufferedImage imageParts = ImageIO.read(ts.getScreenshotAs(OutputType.FILE)); 22 g.drawImage(imageParts, 0, 0, null); 23 } else { 24 int scrollableH = scrollH; 25 int i = 0; 26 27 //スクロールしながらなんどもイメージを結合していく 28 while(scrollableH>innerH){ 29 BufferedImage imageParts = ImageIO.read(ts.getScreenshotAs(OutputType.FILE)); 30 g.drawImage(imageParts, 0, innerH*i, null); 31 scrollableH=scrollableH - innerH; 32 i++; 33 jexec.executeScript("window.scrollTo(0,"+innerH*i+")"); 34 } 35 36 //一番下まで行ったときは、下から埋めるように貼り付け 37 BufferedImage imageParts = ImageIO.read(ts.getScreenshotAs(OutputType.FILE)); 38 g.drawImage(imageParts, 0, scrollH - innerH, null); 39 } 40 41 ImageIO.write(img, "png", new File("c:\temp\mergeimg-"+ System.currentTimeMillis() +".png"));

よろしくお願いいたします。

追加画像①
Spotify

追加画像②
CSS

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

スクロールに追従している要素のほとんどはCSSに

css

1position : fixed;

が指定されており、これを

css

1position : absolute;

に書き換えれば、先頭固定になる事が大半ですが、positionをどのセレクターに指定しているかはサイトの仕様により、まちまちなので毎度調べる必要があると思います。

質問文に挿入された画像のサイト(Spotify)に限った話では以下コードで追従は無くなると思います。

Java

1jexec.executeScript("document.getElementsByTagName('header')[0].style.position = 'absolute'")

またGoogleの検索結果ページ等は、positionを動的にJavaScriptで書き換えてるので全てのサイトで通用する方法は無いかもしれません。(Javaで画像の連結部分を調整すればできるかもしれませんが)

解決はできませんが、参考までに。


追記

JSでは、element(要素)の取得に以下のメソッドを用います。

複数のelementを、配列ライクなオブジェクト(HTMLCollection)を返す

  • document.getElementsByClassName("クラスの名前")
  • document.getElementsByTagName("タグ名")
  • document.getElementsByName("Name属性")

※Elementが複数形でElements

例えば、一番最初のdivであれば、document.getElementsByTagName("div")[0]
二番目のdivであれば、document.getElementsByTagName("div")[1]

として取得できます。

特定の1つのelementを返す

  • document.getElementById("Id")

※Elementが単数形

スタイル優先順位、JSによるインラインスタイルの動的変更

HTMLにおいてスタイルはCSSを用いて指定しますが、CSSは様々な場所から様々な方法指定されています。
それにより、1つの要素に対して2つのスタイルが衝突が発生してしまいます。
衝突時は以下の順番で上書きされていきます。(下が最優先)
※一部高度なものは省略します

  1. 全称セレクタによる指定*{color:pink;}
  2. タグに対する指定 div{color:orange;}
  3. クラスに対する指定 .sample-class-name{color:black;}
  4. idに対する指定 #sample-id{color:blue;}
  5. インラインによる指定 <div style="color:red;"></div>
  6. (!importantによる指定 *{color:pink !important;}

!importantは特殊で、優先順位を無視し最優先になります。

そして、JavaScriptにおいて、

JavaScript

1document.getElementsByClassName("sample-class")[0].style = "position:fixed"

で変更されるのは、上記リストの
** 5. インラインによる指定 <div style="color:red;"></div> **
です。これにより、!importantが宣言されていない限り最優先で変更されます。

したがって…

※HTMLの不要な属性は省略しました

html

1<div id="analysisPg-header" class="header ui-header-fixed ui-header ui-bar-inherit">

こいつに、position=absoluteを指定したい場合は、以下のJSになります。

JavaScript

1document.getElementById('analysisPg-header').style.position = 'absolute'

このJSを実行すると、htmlは以下のように変化します。

html

1<div id="analysisPg-header" class="header ui-header-fixed ui-header ui-bar-inherit" style="position:absolute;">

上述の通り、このように要素に書かれたスタイル(インラインスタイル)は!important指定が無い限り最優先なので変更されます。

投稿2019/04/11 04:14

編集2019/04/11 11:20
kou0179

総合スコア304

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jin007

2019/04/11 04:53

回答ありがとうございます! Spotifyのサイトではヘッダーの固定を解除して撮影できました!(追加画像①) 実際にテストしたいサイトはこのサイト(Spotify)ではないのですが、 テストしたいサイトでも同じようにfixedの処理があり書き換えたところヘッダーの固定が解除されました。 実際はこのhtml文なのですが ``` <div id="analysisPg-header" data-role="header" data-backbtn="false" class="header ui-header-fixed ui-header ui-bar-inherit" role="banner"> (省略) </div> ``` ``` jexec.executeScript("document.getElementsByTagName('header')[0].style.position = 'absolute'") ``` [0]←これは何を指しているものでしょうか? 自分はpositionが上から4つ目(追加画像②参照)だったので、以下のようにしました。 ``` jexec.executeScript("document.getElementsByTagName('header')[3].style.position = 'absolute'") ``` しかし、ログを見ると Cannot read property 'style' of undefined と出ている為styleが読み込めていないように思われます。 申し訳ありませんが再度お力をお借りしたいです。
jin007

2019/04/11 05:09

よく見たら、自分のheaderとなっていませんでした。 divタグですね。。。 特定のdivタグを指定してstyle.positionを書き換えればできる?? 特定のdivタグの指定するには、 idがここにはあるのでidを取得するやり方が一番いいですか??
jin007

2019/04/11 05:23 編集

ーーーーー private WebDriver webDriver; WebElement header; header = webDriver.findElement(By.id("analysisPg-header")); javascriptExecutor.executeScript("document.getElementsByTagName('header')[3].style.position = 'absolute'"); ーーーーー 上記のような実装を考えて入れてみたのですが同じエラー内容でした。 助言を頂けたらと思います。
kou0179

2019/04/11 10:45

ご返信遅くなりました。 Spotifyの方で成功されたようで良かったです。 idがここにはあるのでidを取得するやり方が一番いいですか?? >> HTML5でidはページ内で常に一意でなければならない(重複を禁ず)ので、idが振られているならid指定が一番ですね。 <div id="analysisPg-header" data-role="header" data-backbtn="false" class="header ui-header-fixed ui-header ui-bar-inherit" role="banner"> 恐らくここの「ui-header-fixed」クラスでposition:fixedが定義されているので、ここのdivに対してstyleを指定すれば良い訳です。 注意点としては、上述の通りHTML5でidは常に一意であることが期待されてるので、element取得の結果はHTMLCollectionではありません。 よって、キャプチャを撮りたいサイトが分からないので、正確にお答えはできませんが、おそらく以下のような形になるかと。 jexec.executeScript("document.getElementById('analysisPg-header').style.position = 'absolute'") 後、 header = webDriver.findElement(By.id("analysisPg-header")); は必要ないと思います。
kou0179

2019/04/11 10:48

【追記】 エラーログについてですが、 >>jexec.executeScript("document.getElementsByTagName('header')[3].style.position = 'absolute'") >> しかし、ログを見ると >> Cannot read property 'style' of undefined >> と出ている為styleが読み込めていないように思われます。 ですが、Styleが読みこめてないというよりは、「undefined」=未定義 の style は読めない って事です。 document.getElementsByTagName('header')[3]が存在しない、と言っています。
jin007

2019/04/12 02:31

とても分かりやすい丁寧なご返事ありがとうございます! 実装したところヘッダーの固定が解除されきれいなキャプチャを取得することができました。 もう一点ほど質問させてください。 今回はidが固定なのでdocument.getElementById('analysisPg-header')というようにべた書きしています。 このidを変数で指定することはできますか? 考えたのは、以下の通りですが[SyntaxError: Unexpected token]がでました。 (htmlIdは上記で表記済みとして省略させていただきます) ```java By by = By.id(htmlId); jexec.executeScript(by + ".style.position = 'absolute'"); ``` jsのなかで変数を指定する方法は難しいですか?
kou0179

2019/04/12 02:41 編集

JavaとJavaScriptがゴチャゴチャになってませんか? Java上でレンダリングエンジンを動かして、そいつへJSを文字列として発行しているんですよね? 【JavaScript内で変数を使う】 jexec.executeScript("const htmlId = 'エレメントのID'"); jexec.executeScript("document.getElementById(htmlId).style.position = 'absolute'"); 【Javaの変数からJavaScriptコードに埋め込む例】 ※Javaはほとんど書いた事無いのでミスあるかもしれません。 String htmlId = "エレメントのID"; jexec.executeScript("document.getElementById('"+htmlId+"').style.position = 'absolute'");
jin007

2019/04/12 03:00

"document.getElementById('"+htmlId+"') 変数の組み込み方が分からず苦戦していました。 ()の中でで+を使うんですね! 指定する方法が分からず苦戦していました。 ありがとうございます。成功できそうです! この方法も気になったので試してみます。 http://d.hatena.ne.jp/MoonMtLab/20130831/1377919614
kou0179

2019/04/12 03:03

おお、良かったです! そちらのURLの物は、Java+JSPでWEBサーバーを作り、JSを返した場合なので、今回とは全く違う話とはなります。挑戦してみるのはありだと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問