NET/www/webプログラミング
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*Puppeteer [#puppeteer]
-[[Amexの明細(速報)の自動取得>生活/クレジットカード/為...
-パズル認証や2段階認証は、正面から突破するより、1回は手動...
--(毎回の)パズル認証を(簡単に)回避できたサイト:
---三井住友カード
-headlessだとうまく巡回できない(headlessを無効にすれば順...
-cronで動かすならtry-catchを書かないと、時間切れなど何か...
-[[Webサイトのクローリングやスクリーンショット撮影が簡単...
**Error: Node is either not visible or not an HTMLElement...
単に、指定したセレクタが複数あるだけかも。例えばinput[nam...
#pre{{
let items = await page.$$('input[name="password"]');
items[1].click();
}}
pageクラスと書式が同じものもあれば違うものもある。例えばe...
**sample [#d2d8a5f6]
***新電力 あしたでんき [#add6d35d]
スマートメーターの情報をグラフで表示するページを電力各社...
このサンプルでは、前月のデータをTSVで書き出している。当月...
#pre{{
const puppeteer = require('puppeteer');
const fs = require('fs');
const cheerio = require('cheerio');
const path = require('path');
let tsvfile = path.join(__dirname, 'ashitadenki.tsv');
(async() => {
const browser = await puppeteer.launch({
headless: false,
args: [
'--no-sandbox',
]
});
const page = await browser.newPage();
await page.setViewport({width: 1024, height: 2048});
try {
await page.goto('https://ashita-denki.jp/login/', { wait...
await page.waitForSelector('input#username', {waitUntil:...
await page.focus("input#username");
await page.type("input#username", 'your ID');
await page.focus("input#password");
await page.type("input#password", 'your password');
await page.waitFor(1000);
await page.click('input[type=submit]');
await page.waitForNavigation({waitUntil: 'load'});
await page.waitForSelector('#monthly-report-table', {wai...
var now = new Date();
var month = now.getMonth(); //1月は0
// 前の月を表示する
await page.waitForSelector('#month > form > div:nth-chil...
await page.select('#month > form > div:nth-child(1) > se...
await page.waitFor(3000);
await page.waitForSelector('#monthly-report-table', {wai...
let html = await page.$eval('#monthly-report-table > ul'...
$ = cheerio.load(html);
let lines = [];
$('li').each(function(){
let row = [];
// #monthly-report-table > ul > li:nth-child(1) > time
row.date = $(this).find('time').text().trim();
if (row.date == '') {
return true; //$().eachのnext
}
row.date = row.date.replace(/日/,'');
row.date = month.toFixed() + '/' + row.date;
// #monthly-report-table > ul > li:nth-child(1) > ul > ...
row.kw = $(this).find('ul > li.kwh > span').text().trim...
// #monthly-report-table > ul > li:nth-child(1) > ul > ...
row.cost = $(this).find('ul > li.cost > span').text().t...
lines.push(Object.values(row).join("\t"));
});
fs.writeFile(tsvfile, lines.join("\n"),(err) => {
if (err) throw err;
});
} catch (e) {
console.log('caught');
process.stderr.write(e.toString());
await browser.close();
process.exit(1);
}
await browser.close();
})();
}}
*Node.js [#p5f10848]
**cheerio [#xf897b68]
-不要な要素をcheerioのメソッドで取り除く例:
#pre{{
//table内にあるtableを削除
$('table table').remove();
//8列目が存在しない行を削除。全ての行の内、8列目が不存在...
$('tr:not(:has(td:nth-child(8)))').remove();
//8列目が空の全ての行を削除。全ての行の内、8列目が空の行...
// [注意] 8列目が存在しないと効果なし。8列目がない行を削...
$('tr:has(td:nth-child(8):empty)').remove();
// td.blue以外の全てのtdを削除。全てのtdを、td.blueを除き...
$('td:not(td.blue)').remove();
//一行目(見出し行)を削除
$('tr:nth-child(1)').remove();
}}
*文字コード [#ff17ab4d]
**Perl [#s7554a38]
&aname(urlencode);
-(先ず簡単な方から。)URLエンコードされている文字列を取...
-(これは意外だった。)URLエンコードされている文字列を含...
--「&pre(<:utf8);」ではなく「&pre(<:encoding(UTF-8));」で...
--「binmode IN, ":utf8";」でも同様に駄目になる。
--下記のコードで試せる。
#pre{{
use utf8;
use strict;
use warnings;
use Encode;
use Devel::Peek;
my $str = '%E6%97%85%E8%A1%8C'; # 旅行
my $file = 'test.bin';
my $str_decoded = decode_utf8( &urldecode ($str));
print "basis:$str_decoded\n";
Devel::Peek::Dump($str_decoded);
print qq(\n);
open (OUT, ">$file");
binmode OUT;
print OUT $str;
close OUT;
# -------------------------------------------------------
# デコードせず読み込み
open (IN, "<$file");
#binmode IN;
my $str1_from_file = <IN>;
close IN;
&compare($str,$str1_from_file);
print qq(\n);
# -------------------------------------------------------
# デコードして読み込み
open(IN, '<:utf8', $file);
#binmode IN;
my $str2_from_file = <IN>;
close IN;
&compare($str,$str2_from_file);
# -------------------------------------------------------
# URLデコード
sub urldecode{
my $uri = shift(@_);
$uri =~ tr/+/ /;
$uri =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
return $uri;
}
# 比較
sub compare{
my @sample = @_;
# URLデコード前
&sameornot(@sample);
# URLデコード
my @sample_urldecoded = map {urldecode($_)} @sample;
&sameornot(@sample_urldecoded);
# 内部表現へのデコード
my @sample_decoded = map {decode_utf8($_)} @sample_urlde...
&sameornot(@sample_decoded);
sub sameornot {
$_[0] eq $_[1] ? print "same\n" : print "differnet\n";
}
# 正規表現
if ($sample_decoded[1] =~ /旅行/) {
print "1) regex works\n";
}
# 念のためdecode_utf8前で試す
if ($sample_urldecoded[1] =~ /旅行/) {
print "2) regex works\n";
}
print "compared:$sample_decoded[1]\n";
print "before decode_utf8\n";
Devel::Peek::Dump($sample_urldecoded[1]);
print "after decode_utf8\n";
Devel::Peek::Dump($sample_decoded[1]);
}
}}
--途中「Wide character in print」と言われるが、それが正し...
--このような結果になる。
#pre{{
$ perl test2.pl
Wide character in print at test2.pl line 12.
basis:旅行
SV = PV(0x1018ee0) at 0x1037980
REFCNT = 1
FLAGS = (PADMY,POK,pPOK,UTF8)
PV = 0x110a940 "\346\227\205\350\241\214"\0 [UTF8 "\x{6...
CUR = 6
LEN = 16
same
same
same
1) regex works
Wide character in print at test2.pl line 73.
compared:旅行
before decode_utf8
SV = PVMG(0x10d7a20) at 0x1037188
REFCNT = 1
FLAGS = (POK,pPOK)
IV = 0
NV = 0
PV = 0x1122220 "\346\227\205\350\241\214"\0
CUR = 6
LEN = 16
after decode_utf8
SV = PV(0x1019740) at 0x1037218
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
PV = 0x1097030 "\346\227\205\350\241\214"\0 [UTF8 "\x{6...
CUR = 6
LEN = 16
same
same
differnet
compared:旅行
before decode_utf8
SV = PVMG(0x10d7a50) at 0x10370e0
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
IV = 0
NV = 0
PV = 0x110acb0 "\303\246\302\227\302\205\303\250\302\24...
CUR = 12
LEN = 16
after decode_utf8
SV = PVMG(0x10d7960) at 0x10371e8
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
IV = 0
NV = 0
PV = 0x1030240 "\303\246\302\227\302\205\303\250\302\24...
CUR = 12
LEN = 16
}}
*メモ [#xe473190]
-[[PYPL PopularitY of Programming Language index:http://p...
-printfの記法は気が滅入る。表で値を与えてみた。
--普通の書き方
>printf "<tr><td $tdclr_host>%s<td>%s<td>%s<td>%.60s<td $...
--表で
#pre{{
my @printform = split /\n/, <<END;
<tr>
<td $tdclr_host>%s @{[substr($host,-30)]} %h host, 式展開...
<td>%s $mon $date 日付
<td>%s $clock 時刻
<td>%.60s $uri %rからページ名切り出し
<td $tdclr_stts>%s $stts status code
<td>%.50s $ua User-Agent
</tr>
END
for (@printform) {
@_ = split /\t+/;
if (defined $_[1]) {
printf qq($_[0]),$_[1];
} else {
print qq($_[0]);
}
}
}}
-CGIプログラムをroot名義で動かしたいことがある。sudoを使...
--CGIスクリプトそれ自体をsudoで呼び出し実行する(CGIとし...
-理由不明の文字化けで困っていたが、PerlのCGIモジュールを...
#pre{{
Package namespace installed latest in CPAN file
CGI 3.63 4.38 LEEJO/CGI-...
}}
-use utf8プラグマは、それより前の行に書いてあるリテラルを...
終了行:
#contents
*Puppeteer [#puppeteer]
-[[Amexの明細(速報)の自動取得>生活/クレジットカード/為...
-パズル認証や2段階認証は、正面から突破するより、1回は手動...
--(毎回の)パズル認証を(簡単に)回避できたサイト:
---三井住友カード
-headlessだとうまく巡回できない(headlessを無効にすれば順...
-cronで動かすならtry-catchを書かないと、時間切れなど何か...
-[[Webサイトのクローリングやスクリーンショット撮影が簡単...
**Error: Node is either not visible or not an HTMLElement...
単に、指定したセレクタが複数あるだけかも。例えばinput[nam...
#pre{{
let items = await page.$$('input[name="password"]');
items[1].click();
}}
pageクラスと書式が同じものもあれば違うものもある。例えばe...
**sample [#d2d8a5f6]
***新電力 あしたでんき [#add6d35d]
スマートメーターの情報をグラフで表示するページを電力各社...
このサンプルでは、前月のデータをTSVで書き出している。当月...
#pre{{
const puppeteer = require('puppeteer');
const fs = require('fs');
const cheerio = require('cheerio');
const path = require('path');
let tsvfile = path.join(__dirname, 'ashitadenki.tsv');
(async() => {
const browser = await puppeteer.launch({
headless: false,
args: [
'--no-sandbox',
]
});
const page = await browser.newPage();
await page.setViewport({width: 1024, height: 2048});
try {
await page.goto('https://ashita-denki.jp/login/', { wait...
await page.waitForSelector('input#username', {waitUntil:...
await page.focus("input#username");
await page.type("input#username", 'your ID');
await page.focus("input#password");
await page.type("input#password", 'your password');
await page.waitFor(1000);
await page.click('input[type=submit]');
await page.waitForNavigation({waitUntil: 'load'});
await page.waitForSelector('#monthly-report-table', {wai...
var now = new Date();
var month = now.getMonth(); //1月は0
// 前の月を表示する
await page.waitForSelector('#month > form > div:nth-chil...
await page.select('#month > form > div:nth-child(1) > se...
await page.waitFor(3000);
await page.waitForSelector('#monthly-report-table', {wai...
let html = await page.$eval('#monthly-report-table > ul'...
$ = cheerio.load(html);
let lines = [];
$('li').each(function(){
let row = [];
// #monthly-report-table > ul > li:nth-child(1) > time
row.date = $(this).find('time').text().trim();
if (row.date == '') {
return true; //$().eachのnext
}
row.date = row.date.replace(/日/,'');
row.date = month.toFixed() + '/' + row.date;
// #monthly-report-table > ul > li:nth-child(1) > ul > ...
row.kw = $(this).find('ul > li.kwh > span').text().trim...
// #monthly-report-table > ul > li:nth-child(1) > ul > ...
row.cost = $(this).find('ul > li.cost > span').text().t...
lines.push(Object.values(row).join("\t"));
});
fs.writeFile(tsvfile, lines.join("\n"),(err) => {
if (err) throw err;
});
} catch (e) {
console.log('caught');
process.stderr.write(e.toString());
await browser.close();
process.exit(1);
}
await browser.close();
})();
}}
*Node.js [#p5f10848]
**cheerio [#xf897b68]
-不要な要素をcheerioのメソッドで取り除く例:
#pre{{
//table内にあるtableを削除
$('table table').remove();
//8列目が存在しない行を削除。全ての行の内、8列目が不存在...
$('tr:not(:has(td:nth-child(8)))').remove();
//8列目が空の全ての行を削除。全ての行の内、8列目が空の行...
// [注意] 8列目が存在しないと効果なし。8列目がない行を削...
$('tr:has(td:nth-child(8):empty)').remove();
// td.blue以外の全てのtdを削除。全てのtdを、td.blueを除き...
$('td:not(td.blue)').remove();
//一行目(見出し行)を削除
$('tr:nth-child(1)').remove();
}}
*文字コード [#ff17ab4d]
**Perl [#s7554a38]
&aname(urlencode);
-(先ず簡単な方から。)URLエンコードされている文字列を取...
-(これは意外だった。)URLエンコードされている文字列を含...
--「&pre(<:utf8);」ではなく「&pre(<:encoding(UTF-8));」で...
--「binmode IN, ":utf8";」でも同様に駄目になる。
--下記のコードで試せる。
#pre{{
use utf8;
use strict;
use warnings;
use Encode;
use Devel::Peek;
my $str = '%E6%97%85%E8%A1%8C'; # 旅行
my $file = 'test.bin';
my $str_decoded = decode_utf8( &urldecode ($str));
print "basis:$str_decoded\n";
Devel::Peek::Dump($str_decoded);
print qq(\n);
open (OUT, ">$file");
binmode OUT;
print OUT $str;
close OUT;
# -------------------------------------------------------
# デコードせず読み込み
open (IN, "<$file");
#binmode IN;
my $str1_from_file = <IN>;
close IN;
&compare($str,$str1_from_file);
print qq(\n);
# -------------------------------------------------------
# デコードして読み込み
open(IN, '<:utf8', $file);
#binmode IN;
my $str2_from_file = <IN>;
close IN;
&compare($str,$str2_from_file);
# -------------------------------------------------------
# URLデコード
sub urldecode{
my $uri = shift(@_);
$uri =~ tr/+/ /;
$uri =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
return $uri;
}
# 比較
sub compare{
my @sample = @_;
# URLデコード前
&sameornot(@sample);
# URLデコード
my @sample_urldecoded = map {urldecode($_)} @sample;
&sameornot(@sample_urldecoded);
# 内部表現へのデコード
my @sample_decoded = map {decode_utf8($_)} @sample_urlde...
&sameornot(@sample_decoded);
sub sameornot {
$_[0] eq $_[1] ? print "same\n" : print "differnet\n";
}
# 正規表現
if ($sample_decoded[1] =~ /旅行/) {
print "1) regex works\n";
}
# 念のためdecode_utf8前で試す
if ($sample_urldecoded[1] =~ /旅行/) {
print "2) regex works\n";
}
print "compared:$sample_decoded[1]\n";
print "before decode_utf8\n";
Devel::Peek::Dump($sample_urldecoded[1]);
print "after decode_utf8\n";
Devel::Peek::Dump($sample_decoded[1]);
}
}}
--途中「Wide character in print」と言われるが、それが正し...
--このような結果になる。
#pre{{
$ perl test2.pl
Wide character in print at test2.pl line 12.
basis:旅行
SV = PV(0x1018ee0) at 0x1037980
REFCNT = 1
FLAGS = (PADMY,POK,pPOK,UTF8)
PV = 0x110a940 "\346\227\205\350\241\214"\0 [UTF8 "\x{6...
CUR = 6
LEN = 16
same
same
same
1) regex works
Wide character in print at test2.pl line 73.
compared:旅行
before decode_utf8
SV = PVMG(0x10d7a20) at 0x1037188
REFCNT = 1
FLAGS = (POK,pPOK)
IV = 0
NV = 0
PV = 0x1122220 "\346\227\205\350\241\214"\0
CUR = 6
LEN = 16
after decode_utf8
SV = PV(0x1019740) at 0x1037218
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
PV = 0x1097030 "\346\227\205\350\241\214"\0 [UTF8 "\x{6...
CUR = 6
LEN = 16
same
same
differnet
compared:旅行
before decode_utf8
SV = PVMG(0x10d7a50) at 0x10370e0
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
IV = 0
NV = 0
PV = 0x110acb0 "\303\246\302\227\302\205\303\250\302\24...
CUR = 12
LEN = 16
after decode_utf8
SV = PVMG(0x10d7960) at 0x10371e8
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
IV = 0
NV = 0
PV = 0x1030240 "\303\246\302\227\302\205\303\250\302\24...
CUR = 12
LEN = 16
}}
*メモ [#xe473190]
-[[PYPL PopularitY of Programming Language index:http://p...
-printfの記法は気が滅入る。表で値を与えてみた。
--普通の書き方
>printf "<tr><td $tdclr_host>%s<td>%s<td>%s<td>%.60s<td $...
--表で
#pre{{
my @printform = split /\n/, <<END;
<tr>
<td $tdclr_host>%s @{[substr($host,-30)]} %h host, 式展開...
<td>%s $mon $date 日付
<td>%s $clock 時刻
<td>%.60s $uri %rからページ名切り出し
<td $tdclr_stts>%s $stts status code
<td>%.50s $ua User-Agent
</tr>
END
for (@printform) {
@_ = split /\t+/;
if (defined $_[1]) {
printf qq($_[0]),$_[1];
} else {
print qq($_[0]);
}
}
}}
-CGIプログラムをroot名義で動かしたいことがある。sudoを使...
--CGIスクリプトそれ自体をsudoで呼び出し実行する(CGIとし...
-理由不明の文字化けで困っていたが、PerlのCGIモジュールを...
#pre{{
Package namespace installed latest in CPAN file
CGI 3.63 4.38 LEEJO/CGI-...
}}
-use utf8プラグマは、それより前の行に書いてあるリテラルを...
ページ名: