最終更新日:2019年6月30日 11時57分閲覧回数:932

Opera 12 でセキュア処理できないページをプレビューするスクリプト

スクリーンショット

動作環境

・ XAMPP for Linux 7.2 以上 ・ Opera 12.x

準備

XAMPP for Linux をインストールし、必要に応じて「Mint の起動時に XAMPP を起動する方法」 を参考に設定。

インストール

opera-preview.php を保存し htdocs に置く。
/opt/lampp/htdocs/opera-preview.phpDownload
<?php
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 * (c) 2019 HOT CAT QUERY FEVERS.
 */
error_reporting(-1);
ini_set('max_execution_time'600);
header('x-content-type-options: nosniff');
if (
filter_has_var(INPUT_GET'url'))
{
    
$tor false;
    
$request_uri getenv('REQUEST_URI');
    
$exuri explode('='$request_uri);
    
$segment $exuri[0]. '=';
    
$uri substr_replace($request_uri''0strlen($segment));
    
$uri str_replace('+''%2B'$uri);
    
$url preg_match('/.*\?.*\=.*[\&.*]?/'$uri) || preg_match('/.*\%253F.*\=.*[\%26.*]?/'$uri) ? urldecode($uri) : $uri;
    
$extension strtolower(pathinfo(parse_url($urlPHP_URL_PATH), PATHINFO_EXTENSION));
    
$host parse_url($urlPHP_URL_HOST);
    
$scheme parse_url($urlPHP_URL_SCHEME);
    
$path parse_url($urlPHP_URL_PATH);
    
$query parse_url($urlPHP_URL_QUERY);
    
$server_name 'http://'getenv('SERVER_NAME'). $segment;
    
$filename basename($path);
    
$ads '//html//*
    [
        contains(@href, "impact-ad") or
        starts-with(@class, "mdCmmn") or
        starts-with(@class|@id, "yjads")
    ]'
;
    
$xmls = ['atom''rdf''rss''xml'];
    
$cookie sys_get_temp_dir(). '/'$host;
    if (
$post file_get_contents('php://input')) header('Location: '$server_namestrtok($url'?'). '?'$post);
    
$curl curl($url);
    if (!
$curl && $response_code === 0) exit(http_response_code(503));
    if (
strpos($curl'cdn-cgi/l/chk_jschl') !== false)
    {
        if (!
is_file($cookie) || basename($cookie) !== $host)
            
$curl curl(CloudflareBypass($curl$url), $url);
    }
    
$encoding preg_match('/<(meta|\?xml) .*?(charset=|encoding=)["\']?([\w\-]+)["\']?/i'mb_substr($curl201000), $match) ? mb_preferred_mime_name($match[3]) : 'ASCII,UTF-8,SJIS,JIS,EUC-JP';
    if (
strpos($mime'x-empty') !== false) exit();
    elseif ((
stripos($curl'<rss') !== false && stripos($curl'<html') === false) || array_search($extension$xmls) !== false)
    {
        foreach(
$hd as $phdheader($phd);
        if (!
$curl = @mb_convert_encoding($curl'HTML-ENTITIES'$encoding)) $curl mb_convert_encoding($curl'HTML-ENTITIES''auto');
        
$curl preg_replace('/(<copyright[^>]*>)(.*?)(<\/copyright[^>]*>)/is'''$curl);
        
$curl preg_replace('/(<itunes:[^>]+>.*?<\/itunes:[^>]+>)/is'''$curl);
        
$curl preg_replace('/(about|href|src)=["\']([\w\/:%#\$&\?\(\)~\.=\+\-]+)["\']?/''$1="'$server_name'$2"'$curl);
        
$curl preg_replace('/<\/itunes:[^>]+>/i'''$curl);
        
$curl preg_replace('/<itunes:.* \/>/i'''$curl);
        
$curl preg_replace_callback('/(<content[^>]*>)(.*?)(<\/content[^>]*>)/is''cdata'$curl);
        
$curl preg_replace_callback('/(<description[^>]*>)(.*?)(<\/description[^>]*>)/is''cdata'$curl);
        
$curl preg_replace_callback('/(<guid[^>]*>)(.*?)(<\/guid[^>]*>)/is''xlink'$curl);
        
$curl preg_replace_callback('/(<id[^>]*>)(.*?)(<\/id[^>]*>)/is''xlink'$curl);
        
$curl preg_replace_callback('/(<link[^>]*>)(.*?)(<\/link[^>]*>)/is''xlink'$curl);
        
$curl preg_replace_callback('/(<title[^>]*>)(.*?)(<\/title[^>]*>)/is''cdata'$curl);
        exit(
html_entity_decode($curl));
    }
    elseif (
strpos($mime'html') === false)
    {
        if (
strpos($mime'css') !== false)
        {
            if (
preg_match('/@charset[\s\S]?["\'](.*?)["\'];/'$curl$charset))
            {
                
$encoding $charset[1];
                
$curl str_replace($charset[0], ''$curl);
            }
            
$curl = @mb_convert_encoding($curl'HTML-ENTITIES'$encoding);

            if (
strpos($curl'/*') !== false$curl preg_replace('/\/\*.*?\*\//is'''$curl);
#bg svg
            
if (preg_match_all('/\{(.*?)\}/s'$curl$brackets))
            {
                foreach(
$brackets[1] as $css)
                {
                    if (
strpos($css'background') !== false && strpos($css'svg') !== false && strpos($css'repeat') !== false)
                        
$curl str_replace($css''$curl);
                }
            }
            if (
preg_match('/(@import ?["\'])(.*?)(["\'])/is'$curl))
                
$curl preg_replace_callback('/(@import ?["\'])(.*?)(["\'])/is''export_url'$curl);

            if (
preg_match('/([url|URL] ?\(["\']?)(.*?)(["\']?\))/i'$curl))
                
$curl preg_replace_callback('/([url|URL] ?\(["\']?)(.*?)(["\']?\))/i''export_url'$curl);
#cn font
            
if (strpos($curl'&#65419;&#65422;&#65420;&#34537') !== false)
                
$curl str_replace('&#65419;&#65422;&#65420;&#34537''SimSun'$curl);

            exit(
html_entity_decode($curl));
        }
        else
        {
            
$hd[] = 'Content-Disposition: filename="'$filename'"';
            
rsort($hd);
            foreach(
$hd as $phdheader($phd);
            exit(
$curl);
        }
    }
    else
    {
        
$curl = @mb_convert_encoding($curl'HTML-ENTITIES'$encoding);
        
$dom = new DOMDocument();
        
$dom->formatOutput true;
        
libxml_use_internal_errors(true);
#script
#        if (stripos($curl, '<script') !== false) $curl = preg_replace('/(<script[^>]*>.*?<\/script>)/is', '', $curl);

#space
#        $curl = preg_replace('/(?s)<(pre|code)[^>]*>.*?<\/(pre|code)>(*SKIP)(*F)|\s\s+</', '<', $curl);

        
if ($curl$dom->loadHTML($curl);
        
$xpath = new DOMXPath($dom);
#comment
#        foreach($xpath->query('//comment()') as $comment) if ($comment) $comment->parentNode->removeChild($comment);

#html
        
if ($xpath->query('//html')->length && !$xpath->query('//html')->item(0)->hasAttribute('lang'))
            
$xpath->query('//html')->item(0)->setAttribute('lang''ja');
#base
        
if ($xpath->query('//base')->length && $base $xpath->query('//base')->item(0)->getAttribute('href'))
            
$url $base[0] === '/' dirname($url) : $base;
#title
        
if (isset($xpath->query('//title')->item(0)->textContent))
            
$xpath->query('//title')->item(0)->textContent .= ' - Previewer by HCQF';
#style
        
foreach($xpath->query('//style') as $style)
        {
            if (
$style)
            {
                if (
strpos($style->nodeValue'/*') !== false)
                    
$style->nodeValue preg_replace('/\/\*.*?\*\//s'''$style->nodeValue);
                if (
strpos($style->nodeValue'url') !== false)
                    
$style->nodeValue preg_replace_callback('/([\s|\S]?url[\s|\S]?\(["\']?)(.*?)(["\']?\))/is''export_url'$style->nodeValue);
                if (
preg_match('/(@import[\s\S]?["\'])(.*?)(["\'])/is'$style->nodeValue))
                    
$style->nodeValue preg_replace_callback('/(@import[\s\S]?["\'])(.*?)(["\'])/is''export_url'$style->nodeValue);
            }
        }
#svg
        
foreach($xpath->query('//svg') as $svg)
            if (
$svg && !$svg->hasAttribute('width')) $svg->setAttribute('width''1em');
#noscript
#        foreach($xpath->query('//noscript') as $noscript)
#            if ($noscript && strpos($host, 'wikipedia') === false) $noscript->parentNode->removeChild($noscript);

#option
#        foreach($xpath->query('//option') as $opt)
#            if ($opt && $val = $opt->getAttribute('value')) $opt->setAttribute('value', path2uri($val, $url));

#query
        
if (isset($query))
        {
            if (
strpos($query'start') !== false)
                
$query preg_replace('/search_id=\d+&start=\d+&/'''$query);
            if (
strpos($query'relevance') !== false)
                
$query preg_replace('/page=\d+&q=\w+&o=relevance&/'''$query);
        }
#input type text
        
foreach($xpath->query('//input') as $input)
            if (
$input->getAttribute('type') === 'text' || $input->getAttribute('type') === 'search' || $input->getAttribute('value') === ''$input->setAttribute('style''height: inherit;');
#*
        
foreach($xpath->query('//html//*') as $all)
        {
#on*
#            if ($all->hasAttribute('onclick')) $all->removeAttribute('onclick');

            
if ($all->hasAttribute('class'))
            {
                if (
preg_match('/\s+/'$all->getAttribute('class'))) $all->setAttribute('class'preg_replace('/\s+/'' 'trim($all->getAttribute('class'))));
            }
#style
            
if ($all->hasAttribute('style'))
            {
                if (
$bg preg_replace_callback('/([\s|\S]?url[\s|\S]?\(["\']?)(.*?)(["\']?\))/is''export_url'$all->getAttribute('style'))) $all->setAttribute('style'$bg);
            }
#href
            
if ($href strpos($all->getAttribute('href'), '%') !== false $all->getAttribute('href') : r($all->getAttribute('href')))
            {
                if (
preg_match('|://%\w+[^/]*/|'$href))
                    
$href preg_replace_callback('|(://)(%\w+[^/]*)(/)|', function($m){return $m[1]. idn_to_ascii(urldecode($m[2]), IDNA_DEFAULTINTL_IDNA_VARIANT_UTS46). $m[3];}, $href);
                if (!
$all->hasAttribute('rel') && isset($query) && strpos($href'search.php') !== false)
                    
$all->setAttribute('href'path2uri($href'&'$query$url));
                else
                    
$all->setAttribute('href'path2uri($href$url));
            }
#src
            
if ($all->hasAttribute('data-lazy'))
            {
                
$src $all->getAttribute('data-lazy');
                
$all->removeAttribute('data-lazy');
            }
            elseif (
$all->hasAttribute('data-src'))
            {
                
$src $all->getAttribute('data-src');
                
$all->removeAttribute('data-src');
            }
            elseif (
$all->hasAttribute('file'))
            {
                
$src $all->getAttribute('file');
                
$all->removeAttribute('file');
            }
            else
                
$src $all->getAttribute('src');
            if (
$src$all->setAttribute('src'path2uri($src$url));
#action
            
if ($all->hasAttribute('action') || $all->hasAttribute('method'))
            {
                
$action $all->getAttribute('action');
                
$act path2uri($action$url);
                if (
$action$all->setAttribute('action'$act);
                
$all->setAttribute('method''post');
            }
#background
            
if ($all->hasAttribute('background')) $all->setAttribute('background'path2uri($all->getAttribute('background'), $url));
#poster
            
if ($all->hasAttribute('poster')) $all->setAttribute('poster'path2uri($all->getAttribute('poster'), $url));
        }
#ad
#        foreach($xpath->query($ads) as $ad) if ($ad) $ad->parentNode->removeChild($ad);

#div lazy
        
foreach($xpath->query('//div') as $div)
            if (
$div->hasAttribute('src')) $div->setAttribute('style''background-image: url('$div->getAttribute('src'). ');');

        exit(
$dom->saveHTML($dom->documentElement));
    }
}
function 
r($path)
{
    return 
str_replace(array('%23''%2F''%3A''%3F''%3D'), array('#''/'':''?''='), rawurlencode($path));
}
function 
curl($url$referer='')
{
    global 
$host$post$cookie$tor;
    
$headers = [
        
'Accept-Language: 'getenv('HTTP_ACCEPT_LANGUAGE'),
        
'Accept: 'getenv('HTTP_ACCEPT'),
        
'Cache-Control: 'getenv('HTTP_CACHE_CONTROL'),
        
'Connection: 'getenv('HTTP_CONNECTION'),
        
'DNT: 'getenv('HTTP_DNT'),
        
'Host: '$host
    
];
    
$ch curl_init();
    
curl_setopt($chCURLINFO_HEADER_OUTtrue);
    
curl_setopt($chCURLOPT_AUTOREFERERtrue);
    
curl_setopt($chCURLOPT_ENCODINGgetenv('HTTP_ACCEPT_ENCODING'));
    
curl_setopt($chCURLOPT_FOLLOWLOCATIONtrue);
    
curl_setopt($chCURLOPT_FORBID_REUSEtrue);
    
curl_setopt($chCURLOPT_HEADERfalse);
    
curl_setopt($chCURLOPT_HTTPHEADER$headers);
    
curl_setopt($chCURLOPT_MAXREDIRS5);
    
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
    
curl_setopt($chCURLOPT_SSLVERSIONCURL_SSLVERSION_DEFAULT);
    
curl_setopt($chCURLOPT_TIMEOUT600);
    
curl_setopt($chCURLOPT_URL$url);
    
curl_setopt($chCURLOPT_USERAGENTgetenv('HTTP_USER_AGENT'));
    if (
$referer || is_file($cookie) && basename($cookie) === $host)
    {
        
curl_setopt($chCURLOPT_COOKIE$cookie);
        
curl_setopt($chCURLOPT_COOKIEFILE$cookie);
        
curl_setopt($chCURLOPT_COOKIEJAR$cookie);
        
curl_setopt($chCURLOPT_REFERER$referer);
    }
    else
    {
        global 
$scheme;
        
curl_setopt($chCURLOPT_REFERER$scheme'://'$host);
    }
    
curl_setopt($chCURLOPT_HEADERFUNCTION, function($ch$hd)
    {
        if (
stripos($hd'Content-Type') !== false || stripos($hd'name') !== false$GLOBALS['hd'][] = $hd;
        return 
strlen($hd);
    });
    if (
$tor)
    {
        
curl_setopt($chCURLOPT_PROXY'127.0.0.1');
        
curl_setopt($chCURLOPT_PROXYPORT'9050');
        
curl_setopt($chCURLOPT_PROXYTYPECURLPROXY_SOCKS5_HOSTNAME);
    }
    if (!
$cx curl_exec($ch))
    {
        
curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse);
        
$cx curl_exec($ch);
    }
    if (!
$cx)
    {
        
curl_setopt($chCURLOPT_IPRESOLVECURL_IPRESOLVE_V4);
        
$cx curl_exec($ch);
    }
    
$effective_url curl_getinfo($chCURLINFO_EFFECTIVE_URL);
    
$GLOBALS['mime'] = curl_getinfo($chCURLINFO_CONTENT_TYPE);
    
$GLOBALS['response_code'] = curl_getinfo($chCURLINFO_RESPONSE_CODE);
    
curl_close($ch);
    if (!
$referer && !$post && $url != $effective_url)
    {
        global 
$server_name;
        
header('Location: '$server_name$effective_url);
        exit();
    }
    return 
$cx;
}
function 
path2uri($path$url)
{
    global 
$server_name$scheme;

    if (
substr($path01) === '#' || substr($path05) === 'data:' || substr($path011) === 'javascript:' || substr($path07) === 'mailto:' || substr($path04) === 'tel:')
        return 
$path;

    if (
substr($path01) === '?')
        return 
$server_namestrtok($url'?'). $path;

    if (
strpos($path'http') === 0)
        return 
$server_name$path;

    if (
substr($path02) === '//' && isset($scheme))
        return 
$server_name$scheme':'$path;

    if (
is_numeric($path) && is_numeric(basename($url)))
        return 
$server_namedirname($url). '/'basename($path);

    if (
substr($path01) !== '.' && substr($path01) !== '/' && is_numeric(basename($url)))
        return 
$server_namedirname($url). '/'$path;

    
$exurl explode('/'$url);

    if (!isset(
$exurl[2]) || $path === './')
        return 
$server_namedirname($url);

    
$fqnd $scheme'://'$exurl[2];

    if (!
$exurl parse_url($url))
        return 
$server_name$url;

    
$xpath = isset($exurl['path']) ? $exurl['path'] : '/';
    
$xpath substr($xpath, -1) !== '/' dirname($xpath) : $xpath;

    if (
strpos($path'?') === 0)
        return 
$server_name$fqnd$xpath$path;

    if (
strpos($path'/') === 0)
        return 
$server_name$fqnd$path;

    
$xpathy array_filter(explode('/'$xpath), 'strlen');
    
$endpath end($xpathy);

    if (
strpos($endpath'.') !== falsearray_pop($xpathy);

    foreach(
explode('/'$path) as $expath)
    {
        if (
$expath === '.') continue;
        if (
$expath === '..' && array_pop($xpathy)) continue;
        if (
$expath !== ''$xpathy[] = $expath;
    }
    
$uri $fqnd'/'implode('/'$xpathy);

    if (
substr($path, -1) === '/'$uri .= '/';

    return 
$server_name$uri;
}
function 
cdata($m)
{
    if (
strpos($m[0], 'CDATA') !== false)
        return 
$m[0];
    else
        return 
$m[1]. '<![CDATA['html_entity_decode(str_replace(PHP_EOL''$m[2])). ']]>'$m[3];
}
function 
xlink($m)
{
    global 
$server_name;
    if (isset(
$m[1]))
        return 
$m[1]. $server_namestr_replace('&amp;''%26'trim($m[2])). $m[3];
}
function 
export_url($m)
{
    global 
$scheme$url;
    if (
$n str_replace(array("'"'"'), ''trim($m[2])))
    {
        if (
substr($n02) === '//' && isset($scheme))
            
$n $scheme':'$n;
        if (
strpos($n'data:') !== false)
            return 
$m[1]. $n$m[3];
        else
            return 
$m[1]. path2uri($n$url). $m[3];
    }
}
function 
CloudflareBypass($iuam$url)
{
    
#MIT License
    #Copyright (c) KyranRana
    #https://github.com/KyranRana/cloudflare-bypass/
    
if (preg_match('/(?<=s,t,o,p,b,r,e,a,k,i,n,g,f,\s)(\w+)={"(\w+)":(.+?)(?=})/'$iuam$iuam_jschl_def_matches))
    {
        if (list(
$_$var1$var2$code) = $iuam_jschl_def_matches)
        {
            
preg_match_all('/' $var1 '\.' $var2 '[+\-*\/]?=.+?;/'$iuam$iuam_jschl_matches);
            
$iuam_jschl '';
            
$iuam_jschl .= "\$jschl_answer=$code;\n";
            foreach (
$iuam_jschl_matches[0] as $jschl_match)
                
$iuam_jschl .= str_replace("$var1.$var2"'$jschl_answer'$jschl_match) . "\n";

            
$iuam_jschl str_replace(']+[]''].""'$iuam_jschl);
            
$iuam_jschl str_replace(array('![]''+[]'), 0$iuam_jschl);

            while(
preg_match_all('/\([^()]+\)/'$iuam_jschl$iuam_jschl_eq_matches))
            {
                foreach (
$iuam_jschl_eq_matches[0] as $eq_match)
                {
                    if (
strpos($eq_match'.""') !== false)
                    {
                        
$eq_answer '"'implode('',
                        
array_map(function($match){return eval('return 'str_replace(array('('')'), ''$match). ';');},
                        
array_filter(explode('.""'$eq_match), function($elem){return trim(str_replace(array('('')'), ''$elem)) !== '';}))). '"';
                        
$iuam_jschl str_replace($eq_match$eq_answer$iuam_jschl);
                    }
                    else
                    {
                        if (
strpos($eq_match'"') !== false)
                            
$eq_answer implode('.'array_map(function($match){return strpos($match'"') !== false $match '"'$match'"';}, explode('+'$eq_match)));
                        else
                            
$eq_answer $eq_match;
                        
$eq_answer = eval('return 'str_replace(array('('')'), ''$eq_answer). ';');
                        
$iuam_jschl str_replace($eq_match$eq_answer$iuam_jschl);
                    }
                }
            }
            eval(
$iuam_jschl);
            
preg_match('/name="s" +value="(.+?)"/'$iuam$matches);
            
$s = isset($matches[1]) ? $matches[1] : null;
            
preg_match('/name="jschl_vc" +value="(.+?)"/'$iuam$matches);
            
$jschl_vc = isset($matches[1]) ? $matches[1] : null;
            
preg_match('/name="pass" +value="(.+?)"/'$iuam$matches);
            
$pass = isset($matches[1]) ? $matches[1] : null;
            
$uri parse_url($url);
            
$query = [];
            if (isset(
$uri['query'])) parse_str($uri['query'], $query);
            
$jschl_answer round($jschl_answer10) + mb_strlen($uri['host']);
            
sleep(4);
            return 
sprintf("%s://%s/cdn-cgi/l/chk_jschl?%s"$uri['scheme'], $uri['host'], http_build_query(array_merge(['s' => $s,'jschl_vc' => $jschl_vc'pass' => $pass'jschl_answer' => $jschl_answer], $query)));
        }
    }
}

search.ini に仕込む

~/.opera/search.ini の任意の箇所に下記のコードをペーストし、「xx」の番号などを適宜変更する。 [Search Engine xx] UNIQUEID=xxx Name=Preview Verbtext=0 URL=http://localhost/opera-preview.php?url=%s Query= Key=p Is post=0 UseTLD=0 Has endseparator=0 Encoding=utf-8 Search Type=0 Position=-1 Nameid=0 Deleted=0

使い方

・ プレビューしたいページで、アドレスバーの先頭に「p 」を入力しエンターを押す。 ・ または、「http://localhost/opera-preview.php?url=https://duckduckgo.com/」などとしてブックマークする。 ・ Tor を経由する場合は「$tor = true;」とする。 ・ Javascript や広告を除去したい場合は、該当する行頭の「#」を削除して保存。

注意点

・ Javascript 内の URL を変換していないため、問題が発生する可能性あり → 当該タグの除去を推奨 ・ サイトの構成によっては構造を完全に再現できない → 不要なタグの除去やユーザー CSS の使用を推奨 ・ アクセスログなどの肥大に注意! → /opt/lampp/etc/httpd.conf および php.ini の編集推奨 ・ このページをプレビューするとクラウドフレアと判断される →← ・ 高速化設定非推奨 ・ ダウンロードのダイアログはファイルの読み込みが終わってから表示される → max_execution_time ・ アマゾンで検索キーワードだけが ISO-8859-1 になる謎

追記

画像表示などに時間が掛かる場合は、php.ini を管理者で開いて以下のように編集する。
/opt/lampp/etc/php.ini ; http://php.net/output-buffering output_buffering=40960 ; http://php.net/memory-limit memory_limit=1280M

更新履歴

2018年5月5日初版作成。  ↓ クラウドフレアの DDos 弾きに対応。KyranRana 氏に多謝  ↓ 検索サイトなどのスペース区切りが「+」になる問題を修正  ↓ 画像等の保存時にファイル名が「default」になる問題を修正  ↓ Cookie のファイル名をホスト名に変更  ↓ 数字のみのページャーリンクに対応  ↓ フォントファイルの別途出力  ↓ オプションタグへの適用など  ↓ css の content がデコードされない問題などを修正  ↓ background 等追加  ↓ PHP 7.3.0 で mime が octet-stream になる問題に対応など  ↓ 国際化ドメイン名(IDN)に対応  ↓ input の height を inherit に変更など  ↓ エンコード等修正、div の lazy 追加  ↓ 一部 xpath への変更及び max_execution_time 追加  ↓ サーバーエラーへの対応など  ↓ csv 追加及び js 等タグを除去する際の一例を追加  ↓ https://wired.jp/ などでスクロールに支障を来す svg の繰り返し背景画像を除去  ↓ スクリプト経由のダウンロード処理等変更  ↓ クラウドフレアの DDos 弾き等アップデート  ↓ Tor 追加  ↓ 一部で CURLOPT_SSL_VERIFYPEER を false に  ↓ スタイルシートのキャラセット取得など  ↓ クラウドフレアの DDos 弾きアップデート

コメント

当フォームより収集される個人情報は、返信を要する際に使用されるものであり、法令に基づく行政機関等への提供を除き、ご本人の同意を得ずに第三者に提供することはありません。また、コメントが掲載される場合であってもメールアドレスが本サイト内に記載されることはありません。