Created
October 8, 2016 06:50
-
-
Save toofusan/3d3a67a9a3c9aa4e45583b9bf77d45f7 to your computer and use it in GitHub Desktop.
Webサイト内で「あるURLにどのURLからリンクしているか」抽出する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
const client = require("cheerio-httpcli"); | |
const URL = require("url"); | |
const fs = require("fs"); | |
// 共通変数 | |
const MAX_LEVEL = 5; // 最大遷移回数 | |
// URL | |
if (!process.argv[2]) console.log("No argument"); | |
let TARGET_URL = process.argv[2]; | |
let startURL = checkIndex(TARGET_URL); | |
let savepath = checkDir(TARGET_URL); | |
// 一時格納 | |
let alreadyList = {}; // すでにクロールしたページ | |
let refList = {}; // あるページからの遷移先一覧 | |
let refSourceList = {}; // あるページへの遷移元一覧 | |
let alreadySourceList = {}; // すでにリンク元を抽出したページ | |
let crawlURL = []; // 各遷移回数ごとのクロールURL一覧 | |
crawlURL[0] = [startURL]; | |
// 遷移回数分クローリング | |
console.log("crawling START") | |
for(let i=0;i < MAX_LEVEL; i++) { | |
if(!crawlURL[i]) continue; | |
console.log("crawlURL[" + i + "]: " + crawlURL[i]); | |
crawlURL[i+1] = []; | |
crawlURL[i].forEach(function(val) { | |
crawl(val, i); | |
}); | |
} | |
fs.writeFileSync(savepath + "/linkList.json", JSON.stringify(refList)); | |
console.log("crawl DONE"); | |
// クロール結果から被リンク元抽出 | |
console.log("ref Search START") | |
Object.keys(refList).forEach(function(source) { | |
for(val of this[key]) { | |
refSource(href); | |
} | |
}, refList); | |
fs.writeFileSync(savepath + "/linkSource.json", JSON.stringify(refSourceList)); | |
console.log("ref Search DONE") | |
// ウェブクロール処理 | |
function crawl(url, level) { | |
console.log("crawling : " + url); | |
// exit処理 | |
if (level > MAX_LEVEL) return console.log("Link level over"); // 最大遷移回数で終了 | |
let urlExtention = url.slice(url.length-4, url.length); | |
if (urlExtention === ".pdf" || urlExtention === ".jpg" || urlExtention === ".png") return console.log("Not HTML"); // HTMLではない場合終了 | |
if (alreadyList[url]) return console.log("Already checked"); // すでにクロールしたページの場合は終了 | |
alreadyList[url] = true; | |
if (!url.match(TARGET_URL)) return console.log("Different domain"); // ドメインが変わった場合は終了 | |
// 初期化 | |
refList[url] = []; | |
// ページ内リンク抽出 | |
const fetchResult = client.fetchSync(url); | |
if (fetchResult.error) return console.log("Fetch Error"); | |
fetchResult.$("a").each(function(idx) { | |
var href = this.attribs.href; | |
if(!href || href == "javascript:void(0)" || href == "javascript:void(0);") return true; // リンク設定が無い or javascript呼び出しの場合はスルー | |
href = checkURL(url, href); | |
if(href === "") return true; | |
crawlURL[level+1].push(href); // 次にクロールするURLリストに追加 | |
refList[url].push(href); // クロール中のページからのリンク先一覧に追加 | |
}); | |
refList[url] = Array.from(new Set(refList[url])); // リンク先の重複を削除 | |
} | |
// リンクURL有効化 | |
function checkURL(url, href) { | |
href = URL.resolve(url, href); // 相対パスを絶対パスに変更 | |
href = href.replace(/\#.+$/, ""); // 末尾の"#"以降は無視 | |
href = href.replace(/\#$/, ""); | |
href = checkIndex(href); | |
return href; | |
} | |
// 被リンク元URL抽出処理 | |
function refSource(url) { | |
// exit処理 | |
if (alreadySourceList[url]) return; // すでに抽出したページの場合は終了 | |
alreadySourceList[url] = true; | |
// 初期化 | |
refSourceList[url] = []; | |
// リンク元抽出 | |
const keys = Object.keys(refList); | |
for (let i = 0; i < keys.length; i++) { | |
if (refList[keys[i]].indexOf(url) >= 0) { | |
refSourceList[url].push(keys[i]); | |
} | |
} | |
} | |
// index.htmlをつける | |
function checkIndex(url) { | |
if(url.charAt(url.length - 1) == "/") { | |
return url + "index.html"; | |
} else { | |
return url; | |
} | |
} | |
// ディレクトリ作成 | |
function checkDir(url) { | |
let path = "result/" + url.split("/")[2]; | |
if (!fs.existsSync(path)) { | |
fs.mkdirSync(path); | |
} | |
return path; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment