コンテンツへスキップ

WEBページ「ツリー型リスト」を一括でコピぺしたい。

フツーの表なら矩形選択してからコピペで一括コピーできるんですけど、ツリー的な形式に装飾してあるような一覧だと、うまくコピペできない。
ペーストした時に、行がずれたり、飛んだりしてしまう。 

少しくらいなら、編集しながら頑張れるけど、コピーしたい値の数が多いと無理くてしんどい。
日が暮れる程度ならまだ許容できるけど場合によっては数日かかってしまう。

WEBページ「ツリー型リスト」を一括でコピぺしたい。

WEBページの一覧がうまくコピーできない。

フツーの例

こういった「フツーの表」だったらフツーにコピペできる。

図1: Windchillのアクセス制御規則の一覧テーブル。ふつうの表形式で表示されている。
図1: Windchillのアクセス制御規則の一覧テーブル。ふつうの表形式で表示されている。

選択してコピー、エクセルにペースト。

図2: 表を範囲選択してコピーしている状態。
図2: 表を範囲選択してコピーしている状態。

想定通りにコピペできています。

図3: エクセルに貼り付けた結果。表の内容がズレずにきれいに反映されている。
図3: エクセルに貼り付けた結果。表の内容がズレずにきれいに反映されている。

うまくできない例

こういうツリー構造だと、行がずれてしまったりしてうまくいかない。
しかも、数が多くスクロールさせながら全部コピーするのはしんどい。(ちなみに1500項目程度あって、頑張っても2日くらいかかる。)

図4: Windchillのプリファレンス管理画面。ツリー構造で階層表示された一覧になっている。
図4: Windchillのプリファレンス管理画面。ツリー構造で階層表示された一覧になっている。

選択してコピー、エクセルにペーストしてみる。

図5: ツリー一覧を範囲選択してコピーしている状態。
図5: ツリー一覧を範囲選択してコピーしている状態。

行がズレてしまう。
あと、余計な改行も含まれてしまう。

図6: エクセルに貼り付けた結果。行がズレて、余計な改行も入ってしまっている。
図6: エクセルに貼り付けた結果。行がズレて、余計な改行も入ってしまっている。

というわけで、スクレイピングを使って、WEB ページを解析し、データを成形したいと思う。

WEBページ解析 環境の導入

使用したのはPython とJupyter Notebook です。
(ちなみにターゲットはWindchill という、PTC 製のPDM システムです。)

Python をインストール

https://www.python.org/

Downloads をクリックして、python 最新版をダウンロード。

図7: Python公式サイトのダウンロードページ。Windows版のPython 3.11.0をダウンロードできる。
図7: Python公式サイトのダウンロードページ。Windows版のPython 3.11.0をダウンロードできる。

Install Now を選択して、インストール。
「Add python.exe to PATH」にチェックを入れておきました。PATH に入れておけば何かと便利ですよね。

図8: Pythonインストーラーの画面。「Add python.exe to PATH」にチェックを入れてインストールしている。
図8: Pythonインストーラーの画面。「Add python.exe to PATH」にチェックを入れてインストールしている。

「Disable path length limit」をクリックして実施、「Close」をクリックして閉じる。

図9: インストール完了画面。「Disable path length limit」のリンクが表示されている。
図9: インストール完了画面。「Disable path length limit」のリンクが表示されている。

「Disable path length limit」については下記を参考。

Windows システムのファイル パス形式

「Jupyterlab」をインストール。

使いやすいGUI の開発環境です。
PowerShell (またはコマンドプロンプト)で以下を実行。

pip install jupyterlab
図10: PowerShellで「pip install jupyterlab」を実行しているところ。
図10: PowerShellで「pip install jupyterlab」を実行しているところ。

新しいリリースがあるようなので、notice に従って下記も実行しました。

python.exe -m pip install --upgrade pip
図11: PowerShellで「python.exe -m pip install --upgrade pip」を実行し、pipをアップデートしているところ。
図11: PowerShellで「python.exe -m pip install –upgrade pip」を実行し、pipをアップデートしているところ。

selenium のライブラリをインストール。

pip install selenium
図12: PowerShellで「pip install selenium」を実行しているところ。
図12: PowerShellで「pip install selenium」を実行しているところ。

「jupyter lab」を実行。

jupyter lab

下図のページが開きます。
Notebook のアイコンをクリックすると、Notebook が開きます。

図13: JupyterLabの画面。ファイル一覧とランチャーが表示されていて、Notebookのアイコンをクリックできる。
図13: JupyterLabの画面。ファイル一覧とランチャーが表示されていて、Notebookのアイコンをクリックできる。

この行が「セル」と呼ばれるもので、1セル単位で処理を行って実行結果を反映させることができます。
半インタプリタ、みたいな感じです。

図14: 新規作成したNotebookの、空のセル。
図14: 新規作成したNotebookの、空のセル。

解析に使用するブラウザ・エンジンを設定

jupyter でブラウザを使用できる様にするため、ブラウザのドライバーを入手します。

ChromeDriver – WebDriver for Chrome

図15: ChromeDriverのダウンロードページ。
図15: ChromeDriverのダウンロードページ。

Win32.zip で

図16: ChromeDriver 107.0.5304.62のバージョン別ファイル一覧。win32.zipをダウンロードする。
図16: ChromeDriver 107.0.5304.62のバージョン別ファイル一覧。win32.zipをダウンロードする。

Jupyter のインストールフォルダにでも解凍しておきます。

図17: chromedriver_win32フォルダを、Jupyterのインストールフォルダに解凍して配置しているところ。
図17: chromedriver_win32フォルダを、Jupyterのインストールフォルダに解凍して配置しているところ。

PATH に配置先を指定。

図18: 環境変数のPathに、chromedriver_win32のフォルダパスを追加しているところ。
図18: 環境変数のPathに、chromedriver_win32のフォルダパスを追加しているところ。

Notebook をクリックし、テキスト欄に下記を入力、【Shift】+【Enter】で実行。
(または、再生マークのアイコンをクリックする。)

from selenium import webdriver
test=webdriver.Chrome()
図19: Notebookで「from selenium import webdriver」「test=webdriver.Chrome()」を実行しているセル。
図19: Notebookで「from selenium import webdriver」「test=webdriver.Chrome()」を実行しているセル。

ブラウザが起動されます。

図20: webdriver.Chrome()の実行で起動した、まっさらなブラウザ。「Chromeは自動テストソフトウェアによって制御されています」と表示されている。
図20: webdriver.Chrome()の実行で起動した、まっさらなブラウザ。「Chromeは自動テストソフトウェアによって制御されています」と表示されている。

URL を「.get() 」で渡すと、指定したページを開きます。

test.get("https://zapping.beccou.com")
図21: test.get()でzapping.beccou.comのトップページを開いた状態。
図21: test.get()でzapping.beccou.comのトップページを開いた状態。

「.quit() 」で閉じます。

図22: test.get()でページを開いたあと、test.quit()でブラウザを閉じるコードを実行したセル。
図22: test.get()でページを開いたあと、test.quit()でブラウザを閉じるコードを実行したセル。

使える関数や属性は、ドットを入力したあとにTAB キーを押せばリストが表示されます。
(処理を実行後で具体的に値が入っている状態であれば、その値に対応したメニューが表示されます。)

図23: Notebookでドットのあとにタブキーを押すと、testオブジェクトの属性やメソッドの候補が一覧表示される。
図23: Notebookでドットのあとにタブキーを押すと、testオブジェクトの属性やメソッドの候補が一覧表示される。

WEB ページの解析

WEB ページの解析を行っていきます。
Notebook で処理を実行するときにprint() を使って値を確認しています。
また、ブラウザを非表示モードにせず、動作も確認しながら進めています。

イメージ的には、タグ名やクラス名、ID 等を指定してタグを取得し、オブジェクトの様に使用します。
個人的には、HTML ページの要素をJavascript でオブジェクトっぽく指定するのに近い感じと思います。

認証をクリアする

今回は、Basic 認証で、「http://<user_id>:<user_password>@URL」が有効だった。
(直接ブラウザに上記のフォーマットで入力してもダメですが、python からならOK みたいです。)

arg1=test.get("http://wcadmin:******@wc1202.co.jp/Windchill/app/#ptc1/comp/preference.tree?oid=OR%3Awt.inf.container.ExchangeContainer%3A6&u8=1/")

ボタンを押下してツリーを展開する。

要素の取得が必要になるのですが、記述の方法がselenium 4 以前のバージョンと、4 以降のバージョンで変わってました。

  • selenium 4以前「.find_element_by_xxx(“id”)」
  • selenium 4 以降「.find_element(By.id,”id”)」

 Selenium Python Bindings4. 要素を見つける

これに伴って、4以降のバージョンでは「from selenium.webdriver.common.by import By」による、「By」のインポートも必要。

図24: インストール済みパッケージの一覧。seleniumのバージョンが4.6.0であることが確認できる。
図24: インストール済みパッケージの一覧。seleniumのバージョンが4.6.0であることが確認できる。

4.6 なので、「from selenium.webdriver.common.by import By」を追記。

from selenium import webdriver
from selenium.webdriver.common.by import By
test=webdriver.Chrome()
図25: 「from selenium.webdriver.common.by import By」を追記して、webdriverを起動するコード。
図25: 「from selenium.webdriver.common.by import By」を追記して、webdriverを起動するコード。

F12 キーを押して開発者ツールを表示し、ボタン要素のID を調べる。
結構トライ アンド エラーで頑張ります。

図26: F12の開発者ツールで、ボタン要素のIDを調べているところ。
図26: F12の開発者ツールで、ボタン要素のIDを調べているところ。

ボタンを取得して、クリックする

arg1=test.find_element(By.ID,"netmarkets.preference.treeP349396687912607_shortcutbar")
arg1.click()

ボタンのID が毎回変わるというオニ仕様だったので、結局ID とクラス名で絞り込み取得に変更。

図27: 開発者ツールで、ツールバー要素のIDとクラス名を確認しているところ。
図27: 開発者ツールで、ツールバー要素のIDとクラス名を確認しているところ。
arg1=test.find_element(By.ID,"netmarkets.preference.tree.toolBar")
arg2=arg1.find_element(By.CLASS_NAME,"x-toolbar-cell")
arg2.click()

要素から値を取得する

遅延読み込み、読み込み待ちをするときのウェイト操作用のライブラリを追加

from time import sleep

find で要素を指定して読み込み。

ターゲットページの要素を確認して、データ取得時に何を「キー」にするかを検討。
(開発者ツールでソースを見ると、下記の様なHTML になっていました。)

<table class="x-grid3-row-table " border="0" cellspacing="0" cellpadding="0" style="width:1046.41592920354px">
	<tbody>
		<tr>
			<td class="x-grid3-col x-grid3-cell x-grid3-td-preferenceLocked x-grid3-cell-first " style="width:32px;" tabindex="-1">
				<div class="x-grid3-cell-inner x-grid3-col-preferenceLocked">
					 
				</div>
			</td>
			
			<td class="x-grid3-col x-grid3-cell x-grid3-td-preferenceName " style="width:419.070796460177px;" tabindex="0">
				<div class="ux-maximgb-tg-mastercell-wrap">
					<div class="x-grid3-cell-name-with-norgie" id="ext-gen318">
						<div class="x-grid3-cell-tree-ui">
							<div class="ux-maximgb-tg-uiwrap" style="width: 16px">
								<div style="left: 1px" class="ux-maximgb-tg-elbow-active ux-maximgb-tg-elbow-minus">
									 
								</div>
							</div>
						</div>
						
						<div class="x-grid3-cell-inner x-grid3-col-preferenceName" ext:qtip="Arbortext">
							Arbortext
						</div>
					</div>
				</div>
			</td>
			
			<td class="x-grid3-col x-grid3-cell x-grid3-td-preferenceValue " style="width:120px;" tabindex="-1">
				<div class="x-grid3-cell-inner x-grid3-col-preferenceValue">
					 
				</div>
			</td>
			
			<td class="x-grid3-col x-grid3-cell x-grid3-td-preferenceDescription " style="width:459.34513274336285px;" tabindex="-1">
				<div class="x-grid3-cell-inner x-grid3-col-preferenceDescription" ext:qtip="Arbortext プリファレンス">
					Arbortext プリファレンス
				</div>
			</td>
			
			<td class="x-grid3-col x-grid3-cell x-grid3-td-stretcher x-grid3-cell-last " style="width:1px;" tabindex="-1">
				<div class="x-grid3-cell-inner x-grid3-col-stretcher">
					 
				</div>
			</td>
		</tr>
	</tbody>
</table>

とりあえず、td タブで取得してみる。
複数あるので、find_elements 、配列で取得する。

arg1=test.find_elements(By.TAG_NAME,"td")
print(arg1[0])
図28: find_elementsでtdタグを取得し、先頭の要素を表示させたセル。WebElementオブジェクトが返ってきている。
図28: find_elementsでtdタグを取得し、先頭の要素を表示させたセル。WebElementオブジェクトが返ってきている。

for 文で一覧してみる。

for i in arg1:
    print(i.text)
図29: 開発者ツールの右クリックメニュー。「Copy」の中に「Copy XPath」などの項目が並んでいる。
図29: 開発者ツールの右クリックメニュー。「Copy」の中に「Copy XPath」などの項目が並んでいる。

不要な要素も多く取れている為、td タグのdiv タグとして取得する様に変更

arg1=test.find_elements(By.XPATH,'//td/div')

さらに親のテーブルを指定して取得できるように。
特定できないので諦め。

図30: 開発者ツールで親要素をたどって、テーブルを特定しようとしているところ。
図30: 開発者ツールで親要素をたどって、テーブルを特定しようとしているところ。
図31: for文で取得した要素のテキストを一覧表示した結果。不要な要素も混ざって出力されている。
図31: for文で取得した要素のテキストを一覧表示した結果。不要な要素も混ざって出力されている。

2段階で取得して、個別に分けて取得することにした。

tb=test.find_elements(By.XPATH,'//td/div')
arg1=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceName")
arg2=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceValue")
arg3=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceDescription")
for i in arg1:
    print(i.text)

取得した3つの配列をFOR 文で結合する。FOR 文でカウンターを使用する場合。

for counter, value in enumerate(r):
    print(counter, value.text)

 Python Tips 13. Enumerate

for i,value in enumerate(arg1):
    print(i,"-->",arg1[i].text,":",arg2[i+1].text,":",arg3[i].text)
図32: 3つの配列をenumerateで結合し、「名前:値:説明」の形式で一覧表示した結果。
図32: 3つの配列をenumerateで結合し、「名前:値:説明」の形式で一覧表示した結果。

ウエイト処理の追加

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

触れるようになるまで待つ

wait = WebDriverWait(test, 100)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"x-toolbar-cell")))
図33: WebDriverWaitを使って、要素がクリック可能になるまで待機するコード。
図33: WebDriverWaitを使って、要素がクリック可能になるまで待機するコード。

普通に待機するやつ。

import time
time.sleep(10)time
図34: time.sleep(10)で単純に待機する処理と、取得した要素数をprintで確認しているセル。
図34: time.sleep(10)で単純に待機する処理と、取得した要素数をprintで確認しているセル。

【Python】Seleniumの使用方法メモ

selenium.webdriver.remote.webdriver

スクロールする。

スクロールしないと隠れている部分は読み込まれない。
スクロールし過ぎても読み捨てられてしまう。

1ページくらいずつ、スクロールしながら、読み込みしていきたい。

from selenium.webdriver.common.keys import Keys

残念なことにスクロールしなかったので、ドライバに直接スクロールしているから、エレメント指定は要らない。

キーを送信することに。キー送信はエレメントにするので、取得が必要。Body だとうまくできた。

from selenium.webdriver.common.keys import Keys
p1=test.find_element(By.TAG_NAME,"body")
p1.click()
p1.send_keys(Keys.PAGE_DOWN)

ページ内の値を読み込むくだりから、ループを使って繰り返し処理をつくる。

p1.click()
p1.send_keys(Keys.PAGE_DOWN)
arg_test=["dummy"]
arg1a=arg1
while True:
    print("start")
    time.sleep(1)
    tb=test.find_elements(By.XPATH,'//td/div')
    print(len(tb))
    time.sleep(1)
    arg1a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceName")
    print(len(arg1a))
    if arg_test == arg1a[0]:
        print("BREAK")
        break
    time.sleep(1)
    arg2a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceValue")
    print(len(arg2a))
    time.sleep(1)
    arg3a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceDescription")
    print(len(arg3a))
    for j,value in enumerate(arg1a):
        print(j,"-->",arg1a[j].text,":",arg2a[j].text,":",arg3a[j].text)
    arg_test=arg1a[0]
    p1.click()
    p1.send_keys(Keys.PAGE_DOWN)
    print("done")
図35: ページをスクロールしながらデータを読み込み、繰り返し取得するループ処理のコードと実行結果。
図35: ページをスクロールしながらデータを読み込み、繰り返し取得するループ処理のコードと実行結果。

さらに前回の最終データーと出力を比較して、前回のつつきから出力する様にループを修正したのがこれ。

while True:
    # init flag
    # 1:プリントアウトする 0:しない
    printOn=0
    # comment
    print("start")
    # read elements by tag_name --> div
    time.sleep(1)
    tb=test.find_elements(By.XPATH,'//td/div')
    print(len(tb))
    # select by class_name
    # 1
    time.sleep(1)
    arg1a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceName")
    print(len(arg1a))
    # スクロールして変化がないことの確認
    # データが変わっていない場合、スクロール完了と判定する
    if arg_test == arg1a[0]:
        print("BREAK")
        break
    # 2
    time.sleep(1)
    arg2a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceValue")
    print(len(arg2a))
    # 3
    time.sleep(1)
    arg3a=test.find_elements(By.CLASS_NAME,"x-grid3-col-preferenceDescription")
    print(len(arg3a))
    # marge lists and output
    for j,value in enumerate(arg1a):
        newdata=arg1a[j].text+":"+arg2a[j].text+":"+arg3a[j].text
        # 直前の最終のデータと比較
        if lastdata==newdata:
            printOn=1
        if printOn==2:
            print(j,"-->",arg1a[j].text,":",arg2a[j].text,":",arg3a[j].text)
        # 一回見送り後出力するための調整
        if printOn == 1:
            printOn=2
    # set flag
    arg_test=arg1a[0]
    lastdata=newdata
    # scrool...
    p1.click()
    p1.send_keys(Keys.PAGE_DOWN)
    # comment
    print("done")

カテゴリや小グループ分けの処理

一番簡単なのは、ロケーションを取得して、その値に合わせてインデントを挿入する様にすればいいんじゃないかと。

図36: 取得した要素の座標(location)と、結合したテキストデータをファイルに書き込んでいる結果。
図36: 取得した要素の座標(location)と、結合したテキストデータをファイルに書き込んでいる結果。

座標データは「.values() →list()」で値として取り出せますと。

図37: location.values()を使って、座標データをリストとして取り出す方法を確認しているセル。
図37: location.values()を使って、座標データをリストとして取り出す方法を確認しているセル。
location_data=tb[0].location
list(location_data.values())[0]

全部のデータを読み込んでから、インデントの数を決めたいので、
書き出しの直前に処理を追加するのが良いと思い。。。
ってなると格納先は配列にした方がいいか。

図38: 空のリストを作り、値を追加していく処理を試しているセル。
図38: 空のリストを作り、値を追加していく処理を試しているセル。

X の座標値を書き込むときに同じ値だったら書き込まないようにするところ。
enumerate() は配列だったので、順番に値の比較をする場合は添え字が必要だったお。

こんな感じで、Xの座標値と値のセットを配列に保存。

# 初期化 とりあえず最初の数字を入れておく ※後でソートする。
indent=[(list(arg1[0].location.values())[0])]

# 追加するかしないかのフラグ 0:しない 1:する
add=1
for m in enumerate(indent):
    # indent の中に同じ値があったら追加しない
    print("if m:",m[1])
    if m[1] == x_arg:
        add=0
print(add)
# フラグが1なら値を追加
if add==1:
    indent.append(x_arg)
print(x_arg)

で、こんな感じでインデントにナンバリングします。

for q in enumerate(indent):
    indent[q[0]]=[q[1],q[0]+1]
indent
図39: 座標ごとにインデントの番号を割り振った結果のリスト。
図39: 座標ごとにインデントの番号を割り振った結果のリスト。

データの取り込み時にX のロケーションも一緒に保存。

図40: 取得したテキストデータに、X座標の値も一緒に保存した状態のリスト。
図40: 取得したテキストデータに、X座標の値も一緒に保存した状態のリスト。

あとは書き込みの時にX ロケーションに対応した数の空白を挿入するようにする。

fso=open("test.txt","a")
for u in punch:
    header=""
    for v in indent:
        if v[0]==u[0]:
            addcells=v[1]
    for w in range(addcells):
        header=header+" "
    fso.write(header+u[1])
fso.close

空白を「セル」として先頭に挿入する場合、その後ろがズレてしまうのでその分の調整も入っているやつ。

list.insert(index,value) で追加しようと思ったけど、
よく考えたら文字列にしているので、テキスト処理だった。

ちょっと記述方法などを確認してみる。

図41: 文字列の指定した位置に文字列を挿入する方法を試しているセル。
図41: 文字列の指定した位置に文字列を挿入する方法を試しているセル。

【Python】文字列の指定した位置に文字列を挿入する方法

セルの調整処理を追加後

fso=open("test.txt","w")
for u in punch:
    header=""
    margin=""
    for v in indent:
        if v[0]==u[0]:
            addcells=v[1]
    # 先頭に追加する空白
    for w in range(addcells):
        header=header+":"
    # 一番最後のインデントではない場合、配列の2つ目に残りの空白を追加
    if len(indent)+1!=addcells:
        for y in range(len(indent)-addcells):
            margin=margin+":"
        iidx1=u[1].find(":")
        fso.write(header+u[1][:iidx1+1]+margin+u[1][iidx1:])
        print(header+u[1][:iidx1+1]+margin+u[1][iidx1:])
    else:
        fso.write(header+u[1])
        print(header+u[1])
fso.close()

コロンを区切り文字にしていると、たまにコロンが含まれている文字列が含まれているため、予想外に区切られてしまう。
そういう場合は区切り文字を変更して対応する。

図42: エクセルでテキストファイルを読み込む際の区切り文字選択画面。コロンを区切り文字にすると、値の中のコロンで意図せず分割されてしまう。
図42: エクセルでテキストファイルを読み込む際の区切り文字選択画面。コロンを区切り文字にすると、値の中のコロンで意図せず分割されてしまう。

一括変更できるように、変数に置き換えた。

図43: 区切り文字を変数(sep)に置き換えて、あとから一括で変更できるようにしたコード。
図43: 区切り文字を変数(sep)に置き換えて、あとから一括で変更できるようにしたコード。

ちなみに、エクセルへ読み込むときは、下記の方法で好きな文字を区切り文字にして読み込みしています。

書き出し処理の追加

図44: テキストファイルを書き込みモードで開く処理などを含む、一連のNotebookコード。
図44: テキストファイルを書き込みモードで開く処理などを含む、一連のNotebookコード。
fso=open("test.txt","w+") 
fso.fso.writelines("Strings")
fso.close()

これだけでとりあえず、テキストへの書き出しができるのは便利ですよね。
ちなみにwriteline() を使っても改行が入るわけではなかったっす。

改行したい場合は、文字列の最後に「\n」を挿入します。

書き込み内容を変数で保存して置いて、最後にまとめて書き出し処理しないと読み込み時間がけっこう増える。

Pythonのファイルの書き出し方法まとめ

改行の問題

改行が入っているデータでセルがずれている。

図45: 改行を含むデータをそのまま出力すると、行がズレて表示されてしまった結果。
図45: 改行を含むデータをそのまま出力すると、行がズレて表示されてしまった結果。
図46: 開発者ツールで、1つのセルの中に改行を含む複数行のテキストが入っていることを確認しているところ。
図46: 開発者ツールで、1つのセルの中に改行を含む複数行のテキストが入っていることを確認しているところ。

repr() で改行を文字列として取れた。
(シングルコーテーションで括った状態のデータになりました。)

lastdata=arg1[i].text+":"+repr(arg2[i].text)+":"+arg3[i].text
図47: repr()を使って、改行を文字列として取得した結果。
図47: repr()を使って、改行を文字列として取得した結果。

Pythonで改行を含む文字列の出力、連結、分割、削除、置換

以上です。

smart post preloader
Python Jupyter notebook のポータブル版を作成する。

Python Jupyter notebook のポータブル版を作成する。

会社でjupyter notebook をインストールしようとすると、pip install のコマンドがエラーになってしまう。 社内ネットワークの様な、インタネット未接続の環境でもjupyter notebook を使いたい。 オフライン環境でインストールするには、方法が2つ考えられます。ライブラリをダウンロードしておいてオフラインでインストールする方法と、オンライン環境でインストール済みのju……

Read More
code: 11001, kind: Uncategorized, message: “そのようなホストは不明です。”

code: 11001, kind: Uncategorized, message: “そのようなホストは不明です。”

わかっている人には「そりゃそうでしょ。」みたいな内容かも^^; オフラインでselenium を動かす時にWEBDriver の初期化が失敗する。 オフラインでWEBDriver を使用してスクレイピングする際に、自動化のブラウザが「https://chromedriver.storage.googleapis.com/***」にアクセスしようと試みてエラーになる。 初回のみオンラインにしてURL……

Read More
スクレイピングで、ページ送りしながら表をコピーする。

スクレイピングで、ページ送りしながら表をコピーする。

ツリーから項目を選択し、項目に複数のページがあった場合は最後まで送りながらスクレイピングしていく感じで作成したい。 ループをどうやって定義していけばいいか。 スクレイピングで、ページ送りしながら表をコピーする。 ツリーを順番にクリックしていく とりあえず、URL でできる範囲はなるべくURL で解決します(ツリーの種類指定など)。また、閉じたツリーの展開などは面倒なので手動でやっておきます。 図1……

Read More

(Visited 325 times, 1 visits today)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です