自動滾動頁面,點擊"続きを読む"、"スタンプページへ"、"スタンプ/ポイント確認"、"戻る"按鈕,並在特定首頁點擊第一個文章連結。
// ==UserScript==
// @name NewsFan.jp 自動翻頁和點擊
// @namespace http://tampermonkey.net/
// @version 1.5
// @description 自動滾動頁面,點擊"続きを読む"、"スタンプページへ"、"スタンプ/ポイント確認"、"戻る"按鈕,並在特定首頁點擊第一個文章連結。
// @author lchanc3
// @homepage https://github.com/lchanc3/userscript
// @supportURL https://github.com/lchanc3/userscript/issues
// @match *://*.trepy.jp/*
// @match *://*.life-n.jp/*
// @match *://*.point-news.jp/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// --- 配置 ---
const SCROLL_INTERVAL = 200;
const BUTTON_CHECK_INTERVAL = 300;
const MAX_SCROLL_ATTEMPTS = 10;
const STAMP_PAGE_BUTTON_CHECK_INTERVAL = 500; // Page 2 按鈕檢查頻率
const END_PAGE_BUTTON_CHECK_INTERVAL = 500;
const HOMEPAGE_LINK_CHECK_INTERVAL = 1000; // 首頁連結檢查頻率
const HOMEPAGE_CHECK_TIMEOUT = 15000; // 首頁連結檢查超時 (15秒)
// 目標首頁域名列表
const TARGET_HOMEPAGE_HOSTS = [
'www.trepy.jp',
'www.life-n.jp',
'point-news.jp'
];
const TARGET_HOMEPAGE_PATH = '/sp/';
// --- 輔助函數 ---
function log(message, ...args) {
console.log(`[AutoScript v0.8] ${message}`, ...args);
}
// --- 頁面 1: 滾動頁面邏輯 (article/?article_id=...) ---
function handleScrollingPage() {
log("正在處理滾動頁面 (article)...");
let lastHeight = 0;
let scrollAttempts = 0;
let scrollLoop = null;
let clickLoop = null;
function stopScrollLoop() {
if (scrollLoop) {
clearInterval(scrollLoop);
scrollLoop = null;
log("滾動檢查已停止。");
}
}
function stopClickLoop() {
if (clickLoop) {
clearInterval(clickLoop);
clickLoop = null;
log("按鈕/連結檢查已停止 (滾動頁面)。");
}
}
function autoScroll() {
if (scrollLoop) return; // 防止重複創建
log("啟動滾動檢查...");
scrollLoop = setInterval(() => {
let currentHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight );
window.scrollTo(0, currentHeight);
if (currentHeight === lastHeight) {
scrollAttempts++;
if (scrollAttempts >= MAX_SCROLL_ATTEMPTS) {
log("已達滾動底部或無法再滾動 (嘗試次數: " + scrollAttempts + ")。");
stopScrollLoop();
if (!clickLoop) { // 如果按鈕檢查也停了,重啟以查找 stampLink
findAndClickButtons();
}
}
} else {
// log("滾動中...", currentHeight);
scrollAttempts = 0;
}
lastHeight = currentHeight;
}, SCROLL_INTERVAL);
}
function findAndClickButtons() {
if (clickLoop) return; // 防止重複創建
log("啟動按鈕/連結檢查 (滾動頁面)...");
clickLoop = setInterval(() => {
// 1. 檢查 "続きを読む" 按鈕
let readMoreButton = document.querySelector('[class^="btnNext"]');
if (readMoreButton && readMoreButton.offsetParent !== null) {
log("發現按鈕「続きを読む」,正在點擊...", readMoreButton.className);
readMoreButton.click();
scrollAttempts = 0; // 重置滾動嘗試
if (scrollLoop === null) { // 如果滾動已停止,重新啟動
log("重新啟動滾動檢查 (因點擊続きを読む)。");
autoScroll();
}
// 不需要停止 clickLoop,因為可能還有多個 "続きを読む"
return;
}
// 2. 檢查 "スタンプページへ" 連結
// 只有在滾動確實停止後才尋找此連結
if (scrollLoop === null) {
let stampLink = document.querySelector('.button_stamp a');
if (stampLink && stampLink.offsetParent !== null) {
log("滾動結束,找到「スタンプページへ」連結,準備跳轉...", stampLink.href);
stopClickLoop(); // 找到目標,停止此頁所有檢查
log("停止計時器,執行頁面跳轉至 Stamp 頁。");
window.location.href = stampLink.href;
return;
}
}
// 如果滾動停止了,但 "続きを読む" 和 "スタンプページへ" 都沒找到 (或 "スタンプページへ" 時機未到)
if (scrollLoop === null && !readMoreButton) { // stampLink 的檢查已包含在 scrollLoop === null 條件內
log("滾動結束且未找到目標按鈕/連結「続きを読む」或「スタンプページへ」,停止按鈕檢查。");
stopClickLoop();
}
}, BUTTON_CHECK_INTERVAL);
}
autoScroll();
findAndClickButtons();
}
// --- 頁面 2: Stamp/Point Action 頁面邏輯 (article/page/?article_id=...) ---
function handleStampPage() {
log("正在處理 Stamp/Point Action 頁面 (article/page)...");
let checkPageButtonLoop = null;
function findAndClickPageButton() {
checkPageButtonLoop = setInterval(() => {
// **優先檢查** 新的 Point 按鈕 (btn_point.png)
const pointImage = document.querySelector('.btn_area img[src*="btn_point.png"]');
const pointButtonLink = pointImage ? pointImage.closest('a') : null;
if (pointButtonLink && pointButtonLink.offsetParent !== null) {
log("發現 Point 按鈕/連結 (btn_point.png),準備點擊...", pointButtonLink.href);
clearInterval(checkPageButtonLoop);
log("停止計時器,執行點擊 (Point)。");
pointButtonLink.click();
return;
}
// 如果沒找到 Point 按鈕,再檢查原始的 Stamp 按鈕 (btn_stamp.png)
const stampImage = document.querySelector('.btn_area img[src*="btn_stamp.png"]');
const stampButtonLink = stampImage ? stampImage.closest('a') : null;
if (stampButtonLink && stampButtonLink.offsetParent !== null) {
log("發現 Stamp 確認按鈕/連結 (btn_stamp.png),準備點擊...", stampButtonLink.href);
clearInterval(checkPageButtonLoop);
log("停止計時器,執行點擊 (Stamp)。");
stampButtonLink.click();
return;
}
// log("未找到 Point 或 Stamp 按鈕,繼續檢查...");
}, STAMP_PAGE_BUTTON_CHECK_INTERVAL);
setTimeout(() => {
if (checkPageButtonLoop) {
clearInterval(checkPageButtonLoop);
log("Stamp/Point 頁面按鈕檢查超時,已停止。");
}
}, 30000); // 30 秒
}
findAndClickPageButton();
}
// --- 頁面 3: 結束頁面邏輯 (article/page-end/?article_id=...) ---
function handleEndPage() {
log("正在處理結束頁面 (article/page-end)...");
let checkEndButtonLoop = null;
function findAndClickEndButton() {
checkEndButtonLoop = setInterval(() => {
const endButtonImage = document.querySelector('.btn_com img[src*="btn_return.png"]');
const endButtonLink = endButtonImage ? endButtonImage.closest('a') : null;
if (endButtonLink && endButtonLink.offsetParent !== null) {
log("發現結束頁面按鈕/連結 (btn_return.png),準備點擊...", endButtonLink.href);
clearInterval(checkEndButtonLoop);
log("停止計時器,執行點擊。");
endButtonLink.click();
} else {
// log("未找到結束頁面按鈕,繼續檢查...");
}
}, END_PAGE_BUTTON_CHECK_INTERVAL);
setTimeout(() => {
if (checkEndButtonLoop) {
clearInterval(checkEndButtonLoop);
log("結束頁面按鈕檢查超時,已停止。");
}
}, 30000);
}
findAndClickEndButton();
}
// --- 新功能: 首頁邏輯 (特定網站的 /sp/ 路徑) ---
function handleHomepage() {
log("正在處理首頁 (特定網站 /sp/)...");
let checkHomepageLinkLoop = null;
let homepageCheckTimeoutTimer = null;
function findAndClickFirstArticle() {
// 更新後的選擇器:
// 選擇 div 元素且 class 為 "pon_article_inner",然後選擇其直接子元素 a,
// 且 a 標籤的 href 包含 "/sp/article/?article_id="
const firstArticleLink = document.querySelector('div.pon_article_inner > a[href*="/sp/article/?article_id="]');
if (firstArticleLink && firstArticleLink.offsetParent !== null) {
log("在首頁找到第一個文章連結,準備點擊:", firstArticleLink.href);
if (checkHomepageLinkLoop) clearInterval(checkHomepageLinkLoop);
if (homepageCheckTimeoutTimer) clearTimeout(homepageCheckTimeoutTimer);
log("停止計時器,執行點擊首頁文章連結。");
firstArticleLink.click();
} else {
log("首頁未找到可見的文章連結 (div.pon_article_inner > a),繼續檢查...");
}
}
// 使用 setInterval 進行檢查,因為元素可能延遲載入
checkHomepageLinkLoop = setInterval(findAndClickFirstArticle, HOMEPAGE_LINK_CHECK_INTERVAL);
// 設定超時,如果在一定時間内未找到連結,則停止檢查
homepageCheckTimeoutTimer = setTimeout(() => {
if (checkHomepageLinkLoop) {
clearInterval(checkHomepageLinkLoop);
log("首頁文章連結檢查超時,已停止。");
}
}, HOMEPAGE_CHECK_TIMEOUT);
// 立即執行一次檢查,避免等待第一個 interval
findAndClickFirstArticle();
}
// --- 主邏輯:根據當前 URL 決定執行哪個函數 ---
const currentHref = window.location.href;
const currentHostname = window.location.hostname;
const currentPath = window.location.pathname;
const currentSearch = window.location.search;
log("腳本啟動。當前 URL:", currentHref);
// 判斷頁面類型
if (TARGET_HOMEPAGE_HOSTS.includes(currentHostname) && currentPath === TARGET_HOMEPAGE_PATH) {
handleHomepage(); // 首頁處理
}
else if (currentPath.includes('/sp/article/') && currentSearch.startsWith('?article_id=')) {
if (currentPath.includes('/page-end/')) {
handleEndPage(); // Page 3
} else if (currentPath.includes('/page/')) {
handleStampPage(); // Page 2 (處理 Stamp 或 Point)
} else if (currentPath === '/sp/article/') { // 確保是 /sp/article/ 而不是 /sp/article/page/
handleScrollingPage(); // Page 1
} else {
log("當前頁面路徑包含 /sp/article/ 但不完全匹配已知規則,不執行操作。路徑:", currentPath);
}
}
else {
log("當前頁面不符合任何已定義的處理規則。");
}
})();