This commit is contained in:
Default
2025-03-20 21:10:55 +08:00
parent 62d2e78347
commit b09e4fca11
41 changed files with 1369 additions and 6258 deletions

387
code/123.html Normal file
View File

@@ -0,0 +1,387 @@
<!doctype html>
<html lang='zh'>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Cache-Control" content="no-cache,must-revalidate" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta http-equiv="Cache-Control" content="no-transform" />
<title>御兽我的御主是位恶役大小姐最新章节_御兽我的御主是位恶役大小姐白色的竹篱笆_御兽我的御主是位恶役大小姐小说免费全文阅读_630阅读网</title>
<meta name="keywords" content="御兽:我的御主是位恶役大小姐,白色的竹篱笆丶,630阅读网" />
<meta name="description"
content="关于御兽:我的御主是位恶役大小姐:恶役大小姐伸出手想要推开面前巨龙的脑袋:“混蛋巨龙,不要再吃了!最后一点也没有了!”这里是御兽的世界,这里是御兽师的世界,每个人将会在十五岁时召唤出属于自己的御兽。觉醒,契约,收服,修炼,进化,异化,战斗……是这片大陆的主旋律,山野,城市,战场,秘境,遗迹都有他们的痕迹,御兽资质:甲乙丙丁四等当异世界传奇生物巨龙融合英雄联盟中科加斯能够无限成长的大招被一位恶役,跋扈,淡漠的大小姐召唤觉醒出丁级资质,期间会发生什么故事。" />
<meta http-equiv="mobile-agent" content="format=html5; url=https://m.630read.com/shu/480291.html" />
<link rel="alternate" type="application/vnd.wap.xhtml+xml" media="handheld"
href="https://m.630read.com/shu/480291.html" />
<link href="https://m.630read.com/shu/480291.html" rel="canonical" />
<base href="https://m.630read.com" />
<link href="/app/pc/css/style.css" rel="stylesheet" type="text/css" />
<script>var kdeh2 = "if04kddgsa"; var lg_url = "https%3A%2F%2Fm.630read.com%2Fshu%2F480291.html";</script>
<script src="/tongji/baidutongji.js"></script>
<script>(function () { var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();</script>
<meta property="og:type" content="novel" />
<meta property="og:title" content="御兽:我的御主是位恶役大小姐" />
<meta property="og:description"
content="关于御兽:我的御主是位恶役大小姐:恶役大小姐伸出手想要推开面前巨龙的脑袋:“混蛋巨龙,不要再吃了!最后一点也没有了!”这里是御兽的世界,这里是御兽师的世界,每个人将会在十五岁时召唤出属于自己的御兽。觉醒,契约,收服,修炼,进化,异化,战斗……是这片大陆的主旋律,山野,城市,战场,秘境,遗迹都有他们的痕迹,御兽资质:甲乙丙丁四等当异世界传奇生物巨龙融合英雄联盟中科加斯能够无限成长的大招被一位恶役,跋扈,淡漠的大小姐召唤觉醒出丁级资质,期间会发生什么故事。" />
<meta property="og:image" content="/img/480291.jpg" />
<meta property="og:novel:category" content="玄幻修真" />
<meta property="og:novel:author" content="白色的竹篱笆丶" />
<meta property="og:novel:book_name" content="御兽:我的御主是位恶役大小姐" />
<meta property="og:novel:read_url" content="https://m.630read.com/shu/480291/172582790.html" />
<meta property="og:url" content="https://m.630read.com/shu/480291.html" />
<meta property="og:novel:status" content="连载中" />
<meta property="og:novel:update_time" content="2025-03-18 14:49:04" />
<meta property="og:novel:latest_chapter_name" content="第262章 你不喜欢最好了" />
<meta property="og:novel:latest_chapter_url" content="https://m.630read.com/shu/480291/177226029.html" />
</head>
<body class="novel_info">
<div class="topbar">
<div class="topbar-con">
<div class="topbar-sethome"><a href="javascript:winSetHP();">将本站设为首页</a></div>
<div class="topbar-addfavorite"><a href="javascript:winAddFav()">收藏630阅读网</a></div>
<div class="topbar-right" id="qs_login"><a
href="/login.html?url=https%3A%2F%2Fm.630read.com%2Fshu%2F480291.html">用户登录</a></div>
</div>
</div>
<div class="header">
<h1 class="logo"><a href="/"><span>630阅读网</span></a></h1>
<form id="novel_search" class="search-form" method="post" action="/search.html"><input type="text"
class="input-text input-key" name="s" placeholder="输入书名/作者进行搜索"><button type="submit"
class="btn-tosearch" form="novel_search" value="submit">搜索</button></form>
</div>
<ul class="nav">
<li><a href="/">首 页</a></li>
<li><a href="/list/1/1.html">玄幻修真</a></li>
<li><a href="/list/2/1.html">重生穿越</a></li>
<li><a href="/list/3/1.html">都市小说</a></li>
<li><a href="/list/4/1.html">军史小说</a></li>
<li><a href="/list/5/1.html">网游小说</a></li>
<li><a href="/list/6/1.html">科幻小说</a></li>
<li><a href="/list/7/1.html">灵异小说</a></li>
<li><a href="/list/8/1.html">言情小说</a></li>
<li><a href="/list/9/1.html">其他小说</a></li>
<li><a href="/mybook.html">会员书架</a></li>
<li><a href="/jilu.html">阅读记录</a></li>
</ul>
<div class="container biqunaicc">
<div class="row row-detail">
<div class="layout layout-col1">
<h2 class="layout-tit xs-hidden"><a href="/">630阅读网</a>&gt;<a href="/shu/480291.html">御兽:我的御主是位恶役大小姐</a>
</h2>
<div class="detail-box">
<div class="imgbox"><img alt="御兽:我的御主是位恶役大小姐" src="/img/480291.jpg" /></div>
<div class="info">
<div class="top">
<h1>御兽:我的御主是位恶役大小姐</h1>
<div class="fix">
<p>&nbsp;&nbsp;者:白色的竹篱笆丶</p>
<p class="xs-show">&nbsp;&nbsp;别:玄幻修真</p>
<p class="xs-show">&nbsp;&nbsp;态:连载中</p>
<p class="opt"><span class="xs-hidden">&nbsp;&nbsp;作:</span><a rel="nofollow"
href="javascript:addbookcase('https://m.630read.com/shu/480291.html','480291');">加入书架</a><i
class="xs-hidden"></i><a href="/shu/480291_1.html">章节目录</a><i
class="xs-hidden"></i><a href="/shu/480291/172582790.html">开始阅读</a></p>
<p>最后更新2025-03-18 14:49:04 </p>
<p>最新章节:<a href="/shu/480291/177226029.html">第262章 你不喜欢最好了</a></p>
</div>
</div>
<div class="desc xs-hidden">
关于御兽:我的御主是位恶役大小姐:恶役大小姐伸出手想要推开面前巨龙的脑袋:“混蛋巨龙,不要再吃了!最后一点也没有了!”这里是御兽的世界,这里是御兽师的世界,每个人将会在十五岁时召唤出属于自己的御兽。觉醒,契约,收服,修炼,进化,异化,战斗……是这片大陆的主旋律,山野,城市,战场,秘境,遗迹都有他们的痕迹,御兽资质:甲乙丙丁四等当异世界传奇生物巨龙融合英雄联盟中科加斯能够无限成长的大招被一位恶役,跋扈,淡漠的大小姐召唤觉醒出丁级资质,期间会发生什么故事。
御兽:我的御主是位恶役大小姐</div>
</div>
</div>
</div>
<div class="layout layout-col1">
<h2 class="layout-tit">《御兽我的御主是位恶役大小姐》第262章 你不喜欢最好了</h2>
<div class="first_txt">
<p> 铭城主连连点头,补充说:“不止是位女生,还是个烈女,扬言即便是傲厉殿下在她面前都不敢欺辱她。” 傲慧勾起一个笑容:“有趣。”
跟在傲慧身后的铭城主打磨他这句话半晌,带着上不了台面的权色交易意味说:“调教一个烈女的感觉一定很舒服。” 皇室嘛~,都是滥交之辈,不然道乾那个皇帝也不会有十几位皇子,
“呵呵,本皇子不喜欢烈女,你要是喜欢的话,还是自己留着吧!” 铭城主愣了片刻,想起刚才地牢的发生,那双眼神太可怕了, 他今天必须把这个女人的翅膀折断,不然就只能想办法借助慧殿下的手,把她斩杀,
不然想起她的话,自己指定睡不着觉。 打着这样的算盘,他同傲慧皇子进入了铁砧堡的地牢, ...</p>
<p>相邻推荐:<a href="/shu/480284.html">咒术燃冬???</a>&nbsp;&nbsp;<a
href="/shu/480283.html">春潮泛滥</a>&nbsp;&nbsp;<a
href="/shu/480276.html">穿越后我成了鱼玄机的老师</a>&nbsp;&nbsp;<a
href="/shu/480288.html">四合院:绝世家族</a>&nbsp;&nbsp;<a
href="/shu/480287.html">成为耀眼的一颗星星吧</a>&nbsp;&nbsp;<a
href="/shu/480273.html">大明:捡到朱雄英,调教成恶霸</a>&nbsp;&nbsp;<a
href="/shu/480277.html">重生罪女嫁王爷,渣男全家破大防</a>&nbsp;&nbsp;<a
href="/shu/480281.html">戏神:我不是死神</a>&nbsp;&nbsp;<a
href="/shu/480280.html">三国之风起扬州</a>&nbsp;&nbsp;<a
href="/shu/480279.html">为什么?重生后一切都变啦</a>&nbsp;&nbsp;<a
href="/shu/480275.html">美人很风骚</a>&nbsp;&nbsp;<a
href="/shu/480274.html">明末崛起:打造一个崭新华夏帝国</a>&nbsp;&nbsp;<a
href="/shu/480278.html">见燕台</a>&nbsp;&nbsp;<a
href="https://www.shxsw.com/novel_494159/index.html"
target="_blank">一米八的柳同学</a>&nbsp;&nbsp;<a
href="/shu/480282.html">陶李恋:宫廷异闻录</a>&nbsp;&nbsp;<a
href="/shu/480272.html">原神:美露莘的我不想当抱枕</a>&nbsp;&nbsp;<a
href="/shu/480286.html">在灾难世界收房租</a>&nbsp;&nbsp;<a
href="/shu/480271.html">层层迷雾之都市神探</a>&nbsp;&nbsp;<a
href="/shu/480285.html">群星:我的领袖不太对劲</a>&nbsp;&nbsp;<a
href="/shu/480289.html">闪婚老伴是富豪</a>&nbsp;&nbsp;<a
href="/kan/11207210.html">御兽我的主人实在太稳健了&nbsp;&nbsp;</a><a
href="/kan/11297208.html">御兽我的御主是位恶役大小姐正版阅读&nbsp;&nbsp;</a><a
href="/kan/11207208.html">御兽我的御主是位恶役大小姐&nbsp;&nbsp;</a><a
href="/kan/11534406.html">御兽我的御主是位恶役大小姐免费阅读全文最新章节&nbsp;&nbsp;</a></p>
</div>
</div>
</div>
<div class="row row-section">
<div class="layout layout-col1">
<h2 class="layout-tit">《御兽:我的御主是位恶役大小姐》最新章节</h2>
<ul class="section-list fix">
<li><a href="/shu/480291/177226029.html">第262章 你不喜欢最好了</a></li>
<li><a href="/shu/480291/177226027.html">第261章 操过你</a></li>
<li><a href="/shu/480291/177226024.html">第260章 做局</a></li>
<li><a href="/shu/480291/177226022.html">第259章 拷问</a></li>
<li><a href="/shu/480291/177226020.html">第258章 铁砧堡</a></li>
<li><a href="/shu/480291/177226017.html">第257章 粮食危机</a></li>
<li><a href="/shu/480291/177226015.html">第256章 傲雪天国的圣旨</a></li>
<li><a href="/shu/480291/177226013.html">第255章 蒸汽机和生电机</a></li>
<li><a href="/shu/480291/177226010.html">第254章 昆汀维里迪安</a></li>
<li><a href="/shu/480291/177226008.html">第253章 季是吾留给你季书雨的礼物小章</a></li>
<li><a href="/shu/480291/177226006.html">第253章 德拉克奥姆尼斯王国</a></li>
<li><a href="/shu/480291/177226003.html">第252章 建立吾的王都</a></li>
</ul>
<h2 class="layout-tit">《御兽:我的御主是位恶役大小姐》章节列表</h2>
<ul class="fix section-list">
<li><a href="/shu/480291/172582790.html">第1章 天命御兽</a></li>
<li><a href="/shu/480291/172582792.html">第2章 盛宴天赋启动</a></li>
<li><a href="/shu/480291/172582793.html">第3章 展示敌意</a></li>
<li><a href="/shu/480291/172582796.html">第4章 御兽灵智的展现</a></li>
<li><a href="/shu/480291/172582797.html">第5章 藏茶叶</a></li>
<li><a href="/shu/480291/172582798.html">第6章 震惊季书雨的御兽</a></li>
<li><a href="/shu/480291/172582800.html">第7章 这剑我接了</a></li>
<li><a href="/shu/480291/172582801.html">第8章 掌握飞翔</a></li>
<li><a href="/shu/480291/172582802.html">第9章 抓鱼</a></li>
<li><a href="/shu/480291/172582803.html">第10章 押宝</a></li>
<li><a href="/shu/480291/172582805.html">第11章 御兽师对决</a></li>
<li><a href="/shu/480291/172582806.html">第12章 凭什么</a></li>
<li><a href="/shu/480291/172582807.html">第13章 顾泽与季书雨的亲近</a></li>
<li><a href="/shu/480291/172582808.html">第14章 大丰收的一天</a></li>
<li><a href="/shu/480291/172582810.html">第15章 复杂的春草</a></li>
<li><a href="/shu/480291/172582811.html">第16章 进化的危机</a></li>
<li><a href="/shu/480291/172582812.html">第17章 更名顾泽</a></li>
<li><a href="/shu/480291/172582813.html">第18章 地位</a></li>
<li><a href="/shu/480291/172582817.html">第19章 御兽师与御兽</a></li>
<li><a href="/shu/480291/172582819.html">第20章 对决</a></li>
<li><a href="/shu/480291/172582820.html">第21章 事以密成</a></li>
<li><a href="/shu/480291/172582824.html">第22章 拍卖会</a></li>
<li><a href="/shu/480291/172582825.html">第23章 长雪熊</a></li>
<li><a href="/shu/480291/172582826.html">第24章 黄湮之火</a></li>
<li><a href="/shu/480291/172582828.html">第25章 傲慧到访</a></li>
<li><a href="/shu/480291/172582830.html">第26章 傲慧的打算</a></li>
<li><a href="/shu/480291/172582831.html">第27章 季书雨出品的幼兽丹</a></li>
<li><a href="/shu/480291/172582832.html">第28章 顾内兴泽万民</a></li>
<li><a href="/shu/480291/172582834.html">第29章 踏入丹途的要求</a></li>
<li><a href="/shu/480291/172582835.html">第30章 完不成的任务</a></li>
<li><a href="/shu/480291/172582836.html">第31章 出乎意料</a></li>
<li><a href="/shu/480291/172582837.html">第32章 中品幼兽丹</a></li>
<li><a href="/shu/480291/172582839.html">第33章 夏花的过去</a></li>
<li><a href="/shu/480291/172582841.html">第34章 进阶前兆</a></li>
<li><a href="/shu/480291/172582843.html">第35章 进阶成功</a></li>
<li><a href="/shu/480291/172582846.html">第36章 御兽规则</a></li>
<li><a href="/shu/480291/172582848.html">第37章 家族如何维持</a></li>
<li><a href="/shu/480291/172582849.html">第38章 季礼文的晚宴</a></li>
<li><a href="/shu/480291/172582851.html">第39章 季礼文到来</a></li>
<li><a href="/shu/480291/172582852.html">第40章 完美</a></li>
<li><a href="/shu/480291/172582853.html">第41章 家族大比始端</a></li>
<li><a href="/shu/480291/172582854.html">第42章 狮子搏兔</a></li>
<li><a href="/shu/480291/172582856.html">第43章 碾压的战斗</a></li>
<li><a href="/shu/480291/172582857.html">第44章 神秘的短剑</a></li>
<li><a href="/shu/480291/172582859.html">第45章 不要再恶役了</a></li>
<li><a href="/shu/480291/172582861.html">第46章 对战季言</a></li>
<li><a href="/shu/480291/172582864.html">第47章 惊艳四座的御兽</a></li>
<li><a href="/shu/480291/172582865.html">第48章 我有的是钱</a></li>
<li><a href="/shu/480291/172582866.html">第49章 最后的大比</a></li>
<li><a href="/shu/480291/172582867.html">第50章 三皇子傲厉</a></li>
<li><a href="/shu/480291/172582869.html">第51章 季礼文的选择</a></li>
<li><a href="/shu/480291/172582870.html">第52章 待我封王屠族</a></li>
<li><a href="/shu/480291/172582871.html">第53章 季家千年的守望者</a></li>
<li><a href="/shu/480291/172582872.html">第54章 决裂</a></li>
<li><a href="/shu/480291/172582875.html">第55章 家宴</a></li>
<li><a href="/shu/480291/172582876.html">第56章 启灵大陆</a></li>
<li><a href="/shu/480291/172582877.html">第57章 潇洒的顾泽</a></li>
<li><a href="/shu/480291/172582878.html">第58章 吞食韭树</a></li>
<li><a href="/shu/480291/172582880.html">第59章 城主府</a></li>
<li><a href="/shu/480291/172582881.html">第60章 忘情红</a></li>
<li><a href="/shu/480291/172582882.html">第61章 炉家赴宴</a></li>
<li><a href="/shu/480291/172582883.html">第62章 摆脱奴印的夏花</a></li>
<li><a href="/shu/480291/172582886.html">第63章 离开潭江城的马车</a></li>
<li><a href="/shu/480291/172582888.html">第64章 密林里的猎杀</a></li>
<li><a href="/shu/480291/172582889.html">第65章 整顿出发</a></li>
<li><a href="/shu/480291/172582890.html">第66章 盐城</a></li>
<li><a href="/shu/480291/172582892.html">第67章 关系破冰</a></li>
<li><a href="/shu/480291/172582893.html">第68章 龙骑士</a></li>
<li><a href="/shu/480291/172582894.html">第69章 万宝楼</a></li>
<li><a href="/shu/480291/172582895.html">第70章 一人份</a></li>
<li><a href="/shu/480291/172582897.html">第71章 保鲜期排序</a></li>
<li><a href="/shu/480291/172582899.html">第72章 神秘的蓝发萝莉</a></li>
<li><a href="/shu/480291/172582900.html">第73章 蚀花圣姬门</a></li>
<li><a href="/shu/480291/172582901.html">第74章 花姬秘境</a></li>
<li><a href="/shu/480291/172582903.html">第75章 红衣少女</a></li>
<li><a href="/shu/480291/172582904.html">第76章 御兽</a></li>
<li><a href="/shu/480291/172582905.html">第77章 绝花狼</a></li>
<li><a href="/shu/480291/172582906.html">第78章 boss</a></li>
<li><a href="/shu/480291/172582908.html">第79章 外门弟子</a></li>
<li><a href="/shu/480291/172582909.html">第80章 叶玲</a></li>
<li><a href="/shu/480291/172582911.html">第81章 科加斯</a></li>
<li><a href="/shu/480291/172582913.html">第82章 三峰大堂</a></li>
<li><a href="/shu/480291/172582915.html">第83章 规矩</a></li>
<li><a href="/shu/480291/172582918.html">第84章 培兽师</a></li>
<li><a href="/shu/480291/172582919.html">第85章 副职业</a></li>
<li><a href="/shu/480291/172582921.html">第86章 脚步声的主人</a></li>
<li><a href="/shu/480291/172582923.html">第87章 可以吗</a></li>
<li><a href="/shu/480291/172582926.html">第88章 捕杀森林鹿</a></li>
<li><a href="/shu/480291/172582927.html">第89章 吞噬三阶中期御兽</a></li>
<li><a href="/shu/480291/172582929.html">第90章 宗门主峰</a></li>
<li><a href="/shu/480291/172582931.html">第91章 废丹</a></li>
<li><a href="/shu/480291/172582933.html">第92章 力量型天骄</a></li>
<li><a href="/shu/480291/172582936.html">第93章 炼丹师</a></li>
<li><a href="/shu/480291/172582937.html">第94章 新御兽蛇蛟和海莲女</a></li>
<li><a href="/shu/480291/172582939.html">第95章 红缨</a></li>
<li><a href="/shu/480291/172582941.html">第96章 忧郁萝莉</a></li>
<li><a href="/shu/480291/172582944.html">第97章 地下比赛</a></li>
<li><a href="/shu/480291/172582946.html">第98章 威胁小章</a></li>
<li><a href="/shu/480291/172582948.html">第99章 三阶灵果</a></li>
<li><a href="/shu/480291/172582949.html">第100章 绝花狼首战</a></li>
</ul><a href="/shu/480291_1.html" class="btn-mulu">查看更多章节...</a>
</div>
</div>
<div class="row row-section">
<h2 class="layout-tit">已完结热门小说推荐</h2>
<div class="layout layout-col3">
<div class="item">
<div class="image"><a href="/shu/70829.html"><img style="min-height:120px;" src="/img/70829.jpg"
alt="建造帝国"></a></div>
<dl>
<dt><span>九十年代01</span><a href="/shu/70829.html">建造帝国</a></dt>
<dd style="height:90px"><a href="/shu/70829.html"
style="color: #555">一梦倒流30年来到90年代的杨大利看着包裹里帝国时代的原始驴车城镇中心表示有个卵用然而没多久被生活所迫的他本想着建造城镇中心招募农夫种田搞点...</a>
</dd>
</dl>
</div>
<div class="item">
<div class="image"><a href="/shu/10376.html"><img style="min-height:120px;" src="/img/10376.jpg"
alt="韩娱之单身爸爸"></a></div>
<dl>
<dt><span>夜的七宗罪</span><a href="/shu/10376.html">韩娱之单身爸爸</a></dt>
<dd style="height:90px"><a href="/shu/10376.html"
style="color: #555">2014年1月1日悲剧的李胜林因为和身为李胜基狂粉的女友吵架而被车撞死而附身穿越到了2006年一个同名的韩国人身上。然后居然一个不小心成为了一个单身爸爸接下来就让我们看这个单身爸爸能不能在韩国娱乐圈给自己的宝贝儿子找...</a>
</dd>
</dl>
</div>
<div class="item">
<div class="image"><a href="/shu/154223.html"><img style="min-height:120px;" src="/img/154223.jpg"
alt="花式作死的位面商人"></a></div>
<dl>
<dt><span>张扬的五月</span><a href="/shu/154223.html">花式作死的位面商人</a></dt>
<dd style="height:90px"><a href="/shu/154223.html"
style="color: #555">想要成为一个大商人的叶俊文突然得到了一个跨位面的交易系统,突然间好像无敌了?然而事情没这么简单。这个系统有这三条使用原则一只有对你产生强烈恨意的人才能杀死你,死亡后进行位面跳跃。二同一个人无法杀死你第二次。...</a>
</dd>
</dl>
</div>
<div class="item">
<div class="image"><a href="/shu/39563.html"><img style="min-height:120px;" src="/img/39563.jpg"
alt="仙寇"></a></div>
<dl>
<dt><span>罗玛作品集</span><a href="/shu/39563.html">仙寇</a></dt>
<dd style="height:90px"><a href="/shu/39563.html"
style="color: #555">小说分类其他类型首发状态他站首发小说状态连载中小说作者罗玛作品集授权级别暂未授权全文字数2590448字收藏总数2更新时间20151020...</a>
</dd>
</dl>
</div>
<div class="item">
<div class="image"><a href="/shu/20741.html"><img style="min-height:120px;" src="/img/20741.jpg"
alt="星际烧包女王"></a></div>
<dl>
<dt><span>鱼香蹂丝</span><a href="/shu/20741.html">星际烧包女王</a></dt>
<dd style="height:90px"><a href="/shu/20741.html"
style="color: #555">重生后武力值爆表突破天际,怀揣四颗黑芝麻馅的包子,姐十分无奈,智商极高的小包子们也十分无奈,谁能体谅本女王压力山大?!复兴虫族,多子多孙什么的,千万别来找我啊啊啊啊啊啊人类战斗英雄重生成虫族女王,姐死...</a>
</dd>
</dl>
</div>
<div class="item">
<div class="image"><a href="/shu/42443.html"><img style="min-height:120px;" src="/img/42443.jpg"
alt="全能天才"></a></div>
<dl>
<dt><span>温东篱</span><a href="/shu/42443.html">全能天才</a></dt>
<dd style="height:90px"><a href="/shu/42443.html"
style="color: #555">东篱新书玩美人生求收藏17kcombook6212o6htm1红鸾星动天降桃劫穷小子苏杰在美女董事长肚子里播了个种从此他的人生开始变得与众不同桃劫之下美女纷纷来...</a>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="row">
<div class="layout layout3 layout-col3">
<h2 class="layout-tit">最新标签</h2>
<ul class="txt-list txt-list-row5 tag_news"><a href="/kan/11764952.html">三国美人异传在线阅读</a><a
href="/kan/11764961.html">遇见爱情利</a><a href="/kan/11764980.html">少年欢喜剧本杀答案名字</a><a
href="/kan/11764946.html">曾经的霸主恐龙</a><a href="/kan/11765144.html">重生七零炮灰女配的锦鲤生活</a><a
href="/kan/11765115.html">少有人走的路txt百度</a><a href="/kan/11764949.html">寒门状元农家妻 全文免费阅读尿血的原因</a><a
href="/kan/11765179.html">罪狱岛在哪看</a><a href="/kan/11764928.html">春江有水春江月</a><a
href="/kan/11765091.html">修行世界中形容一个人特别可怕</a><a href="/kan/11765007.html">军长撩妻有度</a><a
href="/kan/11765058.html">光之末裔麦穗</a><a href="/kan/11765170.html">康熙宜妃宠文</a><a
href="/kan/11764943.html">恐龙霸王龙动画</a><a href="/kan/11765004.html">爱做梦的女孩是谁</a><a
href="/kan/11765178.html">帅阿龙个人资料</a><a href="/kan/11765065.html">穿越古代养鸡养鱼种田文</a><a
href="/kan/11765123.html">墨染莲华</a><a href="/kan/11765067.html">穿越异世种田的</a><a
href="/kan/11765095.html">这个快穿有点儿甜txt</a><a href="/kan/11765163.html">幻想世界大穿越番外新世纪</a><a
href="/kan/11765060.html">民间歌谣的特点</a><a href="/kan/11765001.html">我从地狱回来了</a><a
href="/kan/11765006.html">贞观闲王全文免费TXT</a><a href="/kan/11765133.html">食戟之灵的菜品</a><a
href="/kan/11765182.html">绝美青梅的追夫火葬场</a><a href="/kan/11764913.html">春风柳上原百科</a><a
href="/kan/11765165.html">幻想世界主题曲</a><a href="/kan/11765137.html">食戟之灵中的美食放到现实</a><a
href="/kan/11765084.html">不专一的词</a><a href="/kan/11765017.html">接委托吗?晋江</a><a
href="/kan/11764983.html">罗斯玛丽的婴儿全部细节</a><a href="/kan/11764963.html">披着羊皮的大灰狼的</a><a
href="/kan/11764942.html">按需分配了一个alpha62</a><a href="/kan/11764976.html">只是刚好喜欢你TXT百度</a><a
href="/kan/11765104.html">仕途青云路肖致远</a><a href="/kan/11765150.html">我看她她也在看我</a><a
href="/kan/11764900.html">最强赘婿 龙王殿</a><a href="/kan/11765108.html">我的绝色老婆林枫</a><a
href="/kan/11764970.html">游戏即将开始请大家查看身份</a><a href="/kan/11764959.html">不良法医美剧</a><a
href="/kan/11765039.html">天涯客番外1</a><a href="/kan/11764975.html">穿越被富家jk堵门简介</a><a
href="/kan/11764997.html">官官来相护打三个数字</a><a href="/kan/11764906.html">这世界不太好歌词</a><a
href="/kan/11765157.html">重生潜入梦无错版</a><a href="/kan/11765125.html">墨染青衫是什么意思</a><a
href="/kan/11765066.html">穿越到古代养殖的</a><a href="/kan/11765035.html">天涯客番外篇</a><a
href="/kan/11764981.html">寒霄不知长是什么意思</a><a href="/kan/11765149.html">她看向他</a><a
href="/kan/11765079.html">洪荒盘古首徒笔趣阁</a><a href="/kan/11764927.html">春江月歌词</a><a
href="/kan/11765056.html">魅力反派盘点</a><a href="/kan/11765147.html">我看向你</a><a
href="/kan/11765168.html">尘中仙绿茶多少钱</a><a href="/kan/11765085.html">每次相亲都碰到那小子 第二期</a><a
href="/kan/11764940.html">人妻传奇被出卖的</a><a href="/kan/11764903.html">超级兵痞在都市段浪</a><a
href="/kan/11765177.html">宜妃康熙</a><a href="/kan/11764987.html">罗斯玛丽的婴儿真相解析</a><a
href="/kan/11765041.html">生化来袭游戏</a><a href="/kan/11765029.html">宜室宜婚贺帆喜欢女主吗</a><a
href="/kan/11765037.html">天涯客六篇番外4</a><a href="/kan/11764910.html">起风向大海歌曲</a><a
href="/kan/11764993.html">使我思君朝与暮解释</a><a href="/kan/11765142.html">重生七零之炮灰女配</a><a
href="/kan/11764894.html">离婚后!她转身收到六胎孕检单05</a><a href="/kan/11765118.html">鹤俐昀端 知乎</a><a
href="/kan/11764950.html">别想掰弯我林七年完整版</a><a href="/kan/11765141.html">重生七零炮灰妻晋江</a><a
href="/kan/11765101.html">我的姐姐电影演员都是谁</a><a href="/kan/11765070.html">星河梦归处</a><a
href="/kan/11764932.html">隔墙有耳的英文怎么说</a><a href="/kan/11765026.html">总裁爹地太凶猛全文阅读免费</a><a
href="/kan/11765161.html">邪医毒妃多少字</a><a href="/kan/11764925.html">春江月唱词</a><a
href="/kan/11765166.html">幻想世界专辑</a><a href="/kan/11764957.html">寂寞情殇</a><a
href="/kan/11765160.html">你不说我是谁</a><a href="/kan/11765155.html">败给温柔晋江文学城</a><a
href="/kan/11765151.html">她向我走来</a><a href="/kan/11764922.html">肉食系男生什么意思</a><a
href="/kan/11764992.html">重生当了妈妈的</a><a href="/kan/11765040.html">天涯客六篇番外5</a><a
href="/kan/11765083.html">国民老公完整版</a><a href="/kan/11764985.html">罗斯玛丽哈里斯年轻照片</a><a
href="/kan/11764915.html">不可思议的游戏延续篇结局</a><a href="/kan/11764955.html">三国之美人异传顶点</a><a
href="/kan/11765145.html">重生七零炮灰女配又美又娇</a><a href="/kan/11765044.html">我加载了怪谈游戏txt全文</a><a
href="/kan/11764999.html">我从地狱重生归来</a><a href="/kan/11765078.html">洪荒之盘古归来</a><a
href="/kan/11764971.html">游戏即将开始用英语怎么说</a><a href="/kan/11765098.html">木叶之暴风</a><a
href="/kan/11764954.html">三国美人传承</a><a href="/kan/11765092.html">修行世界形容一类事物特别稀少</a><a
href="/kan/11765134.html">食戟之灵什么意思</a><a href="/kan/11765113.html">重生八零年代里当恶婆婆免费</a><a
href="/kan/11765186.html">相女还朝</a><a href="/sitemap_1.xml" target="_blank">网站地图</a></ul>
</div>
</div>
<div class="footer" id="footer">
<div class="pc-footer">
<p>本站所有内容来源于互联网公开且无需登录即可获取的网页内容本站爬虫遵循robots协议若您的网站不希望被本站爬虫抓取可通过屏蔽novelspider字段实现。<br>本站仅对抓取到的内容由程序自动进行排版处理再展现,不涉及更改内容,不针对任何内容表述任何立场。<br>同时您可手动提交相关目标站点网址给我们(站点内容必须允许游客访问,本站爬虫不会抓取需要登录后才展现内容的站点),爬虫程序会依据负载状态自动爬取相关页面。<br>如内容有违规,请通过本站反馈功能提交给我们进行删除处理。
</p>
</div>
</div>
<div id='shuqian'></div>
<script src="/app/pc/js/jquery.min.js"></script>
<script src="/app/pc/js/common.js"></script>
</body>
</html>

72
code/333.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
require 'vendor/autoload.php';
$client = new Client([
'base_uri' => 'https://www.630zw.org',
'http_errors' => false,
'version' => 2.0, // 强制使用 HTTP/2
'timeout' => 160,
'connect_timeout' => 30, // 连接超时 10 秒
'curl' => [
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0, // 强制 HTTP/2
CURLOPT_TCP_KEEPALIVE => 1, // 启用 TCP Keep-Alive
CURLOPT_SSL_VERIFYPEER => true, // 验证 SSL
],
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Mobile Safari/537.36 Edg/134.0.0.0',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Referer' => 'https://www.630zw.org/',
'sec-ch-ua-mobile' => '?1',
'sec-ch-ua-platform' => '"Android"',
'sec-fetch-dest' => 'document',
'sec-fetch-mode' => 'navigate',
'sec-fetch-site' => 'same-origin',
'sec-fetch-user' => '?1',
'upgrade-insecure-requests' => '1',
],
]);
$i = 20284;
while (true) {
$strStartDate = date('Y-m-d H:i:s') . PHP_EOL;
$promises = [];
$j = $i + 15;
for (; $i <= $j; $i++) {
$promises['res' . $i] = $client->getAsync('/shu/' . $i . '.html');
}
// 等待所有请求完成
$responses = Promise\Utils::unwrap($promises);
foreach ($responses as $key => $response) {
// echo "$key: " . $response->getBody() . "\n";
$html = (string) $response->getBody();
$dom = new DOMDocument();
@$dom->loadHTML($html);
$title = $dom->getElementsByTagName('title')->item(0);
$titleText = $title ? $title->textContent : 'No title found';
echo "$key: Title: $titleText\n";
}
$strEndDate = date('Y-m-d H:i:s') . PHP_EOL;
echo $strStartDate;
echo $strEndDate;
}

85
code/444.php Normal file
View File

@@ -0,0 +1,85 @@
<?php
require 'vendor/autoload.php'; // 引入 Composer 自动加载
use MongoDB\Client;
use MongoDB\Exception\Exception as MongoDBException;
class MongoSequenceGenerator {
private $client;
private $db;
// 构造函数,初始化 MongoDB 连接,带 IP、用户名和密码
public function __construct($uri, $dbName) {
try {
$this->client = new Client($uri);
$this->db = $this->client->selectDatabase($dbName);
} catch (MongoDBException $e) {
die("MongoDB connection failed: " . $e->getMessage());
}
}
// 获取下一个自增序列值
public function getNextSequence($sequenceName) {
try {
$counters = $this->db->selectCollection('counters');
$result = $counters->findOneAndUpdate(
['_id' => $sequenceName],
['$inc' => ['sequence_value' => 1]],
[
'upsert' => true, // 如果不存在则创建
'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER // 返回更新后的文档
]
);
// 如果是第一次创建sequence_value 可能为 null初始化为 1
if ($result === null || !isset($result->sequence_value)) {
return 1;
}
return $result->sequence_value;
} catch (MongoDBException $e) {
throw new Exception("Failed to generate sequence: " . $e->getMessage());
}
}
// 示例:插入用户数据
public function insertUser($name, $age) {
try {
$userId = $this->getNextSequence('userId');
$users = $this->db->selectCollection('users');
$result = $users->insertOne([
'_id' => $userId,
'name' => $name,
'age' => $age,
'created_at' => new MongoDB\BSON\UTCDateTime()
]);
return $result->getInsertedId();
} catch (MongoDBException $e) {
throw new Exception("Failed to insert user: " . $e->getMessage());
}
}
}
// 使用示例
try {
// 设置你的 MongoDB 连接信息
$mongoUri = 'mongodb://admin:qq123123@127.0.0.1:27017'; // 替换为你的 IP、用户名和密码
$dbName = 'test001'; // 替换为你的数据库名
$generator = new MongoSequenceGenerator($mongoUri, $dbName);
// 插入几个测试用户
$id1 = $generator->insertUser('Alice', 25);
echo "Inserted user with ID: " . $id1 . "\n";
$id2 = $generator->insertUser('Bob', 30);
echo "Inserted user with ID: " . $id2 . "\n";
$id3 = $generator->insertUser('Charlie', 35);
echo "Inserted user with ID: " . $id3 . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>

View File

@@ -6,7 +6,7 @@ namespace app\task\collection;
use app\model\CaiJiPeiZhiModel;
use app\model\SystemConfigModel;
use app\task\core\TaskCore;
use minserver\QueueManage;
use GuzzleHttp\Client;
/**
@@ -24,9 +24,9 @@ class PullDataColBase
/**
* Undocumented variable
*
* @var \app\task\core\TaskCore
* @var \minserver\QueueManage
*/
protected $TaskCore = NULL;
protected $QueueManage = NULL;
protected $arrCaiJiPeiZhi = [];
@@ -34,7 +34,7 @@ class PullDataColBase
{
$this->Client = new Client();
$this->TaskCore = new TaskCore();
$this->QueueManage = new QueueManage();
}

View File

@@ -1,427 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\biquxs;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class BiquxsXiaoShuoCol extends PullDataColBase
{
public function pullXiaoShuo()
{
$TaskCore = $this->TaskCore;
// 20054
for ($i = 1; $i <= 20054; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_source_id' => $i,
'xs_source_seo_id' => 1,
]
];
$TaskCore->set($arrTask);
var_dump($arrTask);
}
}
public function getNovelInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->getBiquxsDomain();
$strUrl = 'http://www.biquxs.com/book/' . $arrData['xs_source_id'] ; //'http://www.biquxs.com/book/20053';
$intXiaoShuoSourceId = $arrData['xs_source_id']; //20053;
$intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id']; //1 ;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// var_dump($QueryList);
// 提取所有 <meta> 标签的属性
$result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
return [
'property' => $item->attr('property'),
'content' => $item->attr('content'),
];
});
// 打印结果
// print_r($result->all());
$strZuoZhe = '';
$strMingZi = '';
$strLastDate = '';
$strJieShao = '';
$strCover = '';
$strFenlei = '';
$strZiShu = 0;
$strZhuangTai = $QueryList->find('#info p')->eq(1)->text();
$strZhuangTai = getStringAfterWord($strZhuangTai, '状态:');
foreach ($result as $item) {
switch ($item['property']) {
case 'og:title':
$strMingZi = $item['content'];
break;
case 'og:description':
$strJieShao = $item['content'];
break;
case 'og:image':
$strCover = $item['content'];
break;
case 'og:book:category':
$strFenlei = $item['content'];
break;
case 'og:book:author':
$strZuoZhe = $item['content'];
break;
case 'og:book:update_time':
$strLastDate = $item['content'];
break;
}
}
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadImage( $intXiaoShuoSourceId,$strCover, 'xs');
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
$arrCover = [
'code' => 'BI_QU_XS_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strFenleiIId = 1 ;
switch ($strFenlei) {
case '玄幻小说':
$strName = "玄幻";
$strFenleiIId = 1;
break;
case '修真小说':
$strName = "修真";
$strFenleiIId = 2;
break;
case '都市小说':
$strName = "都市";
$strFenleiIId = 3;
break;
case '历史小说':
$strName = "历史";
$strFenleiIId = 4;
break;
case '网游小说':
$strName = "网游";
$strFenleiIId = 5;
break;
case '科幻小说':
$strName = "科幻";
$strFenleiIId = 6;
break;
case '女频小说':
$strName = "女频";
$strFenleiIId = 7;
break;
case '其它小说':
$strName = "其它";
$strFenleiIId = 8;
break;
default:
$strName = "其它";
$strFenleiIId = 8;
break;
}
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe , //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $strFenleiIId,
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceId.'1',
'xsxq_source_code' => 'BIQU_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
$arrZhangjie = [];
$intChapterIndex = 0; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryList->find('.listmain a')->count() > 0) {
$QueryList->find('.listmain a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// 从索引6开始
if ($intChapterIndex >= 5) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
}
$intChapterIndex++;
});
// 输出最终结果
var_dump($arrZhangjie);
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
//unset($QueryList);
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuoSourceId)
->max('xszj_pai_xu'); // 获取最大值
var_dump('获取小说章节最大值-'.$intMaxXiaoShuoZhangJiePaixu);
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
var_dump("小说章节已经入库,不再推送任务");
continue;// 如果任务已存在,直接跳过 break
}
$strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
$strZhangJieId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = 'AILISI_XIAOSHUO_ZHANGJIE_'. $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieId;
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieId,
'xszj_paixu' => $intZhangJieNum,
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_source_id' => $XiaoShuoXiangQingModel->xsxq_source_id,
'xsfl_id' => $strFenleiIId,
]
];
$TaskCore->set($arrTask);
}
var_dump("章节任务投递成功");
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
var_dump('getNovelReader');
var_dump($arrData['xszj_url']);
$Client = $this->Client;
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoSourceID = $arrData['xsxq_source_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
$strZhangJieName = $arrData['xszj_name'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$ZhangJieQueryList = QueryList::html($strResult);
// 获取原始 HTML
$strNeiRong = $ZhangJieQueryList->find('#content')->eq(0)->html();
// 解码 HTML 实体
$strNeiRong = html_entity_decode($strNeiRong, ENT_QUOTES, 'UTF-8');
// 去掉 <p> 标签中的 class="content_detail" 属性
$strNeiRong = preg_replace('/<p\s+class="content_detail"/i', '<p', $strNeiRong);
// 清理多余的 HTML 标签
$strNeiRong = strip_tags($strNeiRong, '<p>');
// 替换不间断空格 (\xc2\xa0) 和 &nbsp; 为普通空格
$strNeiRong = preg_replace('/\xc2\xa0/', ' ', $strNeiRong); // 替换 UTF-8 不间断空格
$strNeiRong = preg_replace('/&nbsp;/', ' ', $strNeiRong); // 替换 &nbsp;
// 清理多余空格和换行符
$strNeiRong = preg_replace('/\s+/', ' ', $strNeiRong);
$strNeiRong = preg_replace('/<p>\s+/', '<p>', $strNeiRong); // 清理 <p> 标签内部多余空格
$strNeiRong = preg_replace('/\s+<\/p>/', '</p>', $strNeiRong); // 清理 <p> 标签结尾多余空格
// 输出结果
// var_dump($strNeiRong);
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel").'/novel/biquxs/'.$intFenleiId.'/'.$intXiaoShuoSourceID.'/'.$strZhangJieSourceId.'.txt';
//$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']) ;
} else {
var_dump("Error: " . $result['message']) ;
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoSourceID,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
];
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
unset($ZhangJieQueryList);
// 延时 3 秒
//sleep(3);
} catch (\Throwable $T) {
throw $T;
}
}
}

View File

@@ -1,545 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\ccc5;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class XiaoShuo5cccCol extends PullDataColBase
{
public function pullXiaoShuo()
{
$TaskCore = $this->TaskCore;
// 20054
for ($i = 3; $i <= 3; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_source_id' => $i,
'xs_source_seo_id' => 1,
]
];
$TaskCore->set($arrTask);
var_dump($arrTask);
}
}
public function getNovelInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->get5cccDomain();
$strUrl = 'https://www.5ccc.org/chapter/' . $arrData['xs_source_id'].'.html' ; //'http://www.biquxs.com/book/20053';
$intXiaoShuoSourceId = $arrData['xs_source_id']; //20053;
$intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id']; //1 ;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// var_dump($QueryList);
// 提取所有 <meta> 标签的属性
$result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
return [
'property' => $item->attr('property'),
'content' => $item->attr('content'),
];
});
// 打印结果
print_r($result->all());
$strZuoZhe = '';
$strMingZi = '';
$strLastDate = '';
$strJieShao = '';
$strCover = '';
$strFenlei = '';
$strZiShu = 0;
$strZhuangTai = "";
foreach ($result as $item) {
switch ($item['property']) {
case 'og:title':
$strMingZi = $item['content'];
break;
case 'og:description':
$strJieShao = $item['content'];
break;
case 'og:image':
$strCover = $item['content'];
break;
case 'og:novel:category':
$strFenlei = $item['content'];
break;
case 'og:novel:author':
$strZuoZhe = $item['content'];
break;
case 'og:novel:update_time':
$strLastDate = $item['content'];
break;
case 'og:novel:status':
$strZhuangTai = $item['content'];
break;
}
}
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
$strCover = $QueryList->find('.imgbox img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadImage( $intXiaoShuoSourceId,$strCover, 'xs');
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
$arrCover = [
'code' => '5CCC_XS_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strFenleiIId = 1 ;
switch ($strFenlei) {
case '玄幻修真':
$strName = "玄幻修真";
$strFenleiIId = 1;
break;
case '重生穿越':
$strName = "重生穿越";
$strFenleiIId = 2;
break;
case '都市小说':
$strName = "都市小说";
$strFenleiIId = 3;
break;
case '军史小说':
$strName = "军史小说";
$strFenleiIId = 4;
break;
case '网游小说':
$strName = "网游小说";
$strFenleiIId = 5;
break;
case '科幻小说':
$strName = "科幻小说";
$strFenleiIId = 6;
break;
case '灵异小说':
$strName = "灵异小说";
$strFenleiIId = 7;
break;
case '言情小说':
$strName = "言情小说";
$strFenleiIId = 8;
break;
case '其他小说':
$strName = "其他小说";
$strFenleiIId = 9;
break;
}
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe , //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $strFenleiIId,
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceId.'1',
'xsxq_source_code' => 'BIQU_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
$strMuluHref = $QueryList->find('.btn-mulu')->eq(0)->attr("href");
$arrTask = [
'callback' => [self::class, 'getNovelReaderAll'],
'data' => [
'xszj_href' => $strMuluHref,
]
];
$TaskCore->set($arrTask);
/*
$arrZhangjie = [];
$intChapterIndex = 0; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryList->find('.section-list a')->count() > 0) {
$QueryList->find('.section-list a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// 从索引6开始
//if ($intChapterIndex >= 5) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
//}
$intChapterIndex++;
});
// 输出最终结果
var_dump($arrZhangjie);
} else {
echo "No elements found for .section-list a" . PHP_EOL;
}
//unset($QueryList);
var_dump($arrZhangjie);
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuoSourceId)
->max('xszj_pai_xu'); // 获取最大值
var_dump($intMaxXiaoShuoZhangJiePaixu);
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
var_dump("小说章节已经入库,不再推送任务");
continue;// 如果任务已存在,直接跳过 break
}
$strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
$strZhangJieId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = '5CCC_XIAOSHUO_ZHANGJIE_'. $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieId;
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieId,
'xszj_paixu' => $intZhangJieNum,
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_source_id' => $XiaoShuoXiangQingModel->xsxq_source_id,
'xsfl_id' => $strFenleiIId,
]
];
$TaskCore->set($arrTask);
var_dump("章节任务投递成功".$strXszjSourceCode);
}
*/
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReaderAll($arrData)
{
var_dump('getNovelReaderAll');
$strMuluHref = $arrData['xszj_href'];
var_dump($strMuluHref);
$Client = $this->Client;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strMuluHref);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strMuluHref, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$QueryList = QueryList::html($strResult);
$intChapterIndex = 0; // 定义一个计数器变量
var_dump($QueryList->find('.section-list a')->count());
// 检查是否找到元素
if ($QueryList->find('.section-list a')->count() > 0) {
$QueryList->find('.section-list a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// 从索引6开始
//if ($intChapterIndex >= 5) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
//}
$intChapterIndex++;
});
// 输出最终结果
var_dump($arrZhangjie);
} else {
echo "No elements found for .section-list a" . PHP_EOL;
}
//unset($QueryList);
var_dump($arrZhangjie);
/*
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuoSourceId)
->max('xszj_pai_xu'); // 获取最大值
var_dump($intMaxXiaoShuoZhangJiePaixu);
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
var_dump("小说章节已经入库,不再推送任务");
continue;// 如果任务已存在,直接跳过 break
}
$strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
$strZhangJieId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = '5CCC_XIAOSHUO_ZHANGJIE_'. $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieId;
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieId,
'xszj_paixu' => $intZhangJieNum,
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_source_id' => $XiaoShuoXiangQingModel->xsxq_source_id,
'xsfl_id' => $strFenleiIId,
]
];
$TaskCore->set($arrTask);
var_dump("章节任务投递成功".$strXszjSourceCode);
}
*/
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
var_dump('getNovelReader');
var_dump($arrData['xszj_url']);
$Client = $this->Client;
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoSourceID = $arrData['xsxq_source_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
$strZhangJieName = $arrData['xszj_name'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$ZhangJieQueryList = QueryList::html($strResult);
// 获取原始 HTML
$strNeiRong = $ZhangJieQueryList->find('#content')->eq(0)->html();
// 解码 HTML 实体
$strNeiRong = html_entity_decode($strNeiRong, ENT_QUOTES, 'UTF-8');
// 去掉 <p> 标签中的 class="content_detail" 属性
$strNeiRong = preg_replace('/<p\s+class="content_detail"/i', '<p', $strNeiRong);
// 清理多余的 HTML 标签
$strNeiRong = strip_tags($strNeiRong, '<p>');
// 替换不间断空格 (\xc2\xa0) 和 &nbsp; 为普通空格
$strNeiRong = preg_replace('/\xc2\xa0/', ' ', $strNeiRong); // 替换 UTF-8 不间断空格
$strNeiRong = preg_replace('/&nbsp;/', ' ', $strNeiRong); // 替换 &nbsp;
// 清理多余空格和换行符
$strNeiRong = preg_replace('/\s+/', ' ', $strNeiRong);
$strNeiRong = preg_replace('/<p>\s+/', '<p>', $strNeiRong); // 清理 <p> 标签内部多余空格
$strNeiRong = preg_replace('/\s+<\/p>/', '</p>', $strNeiRong); // 清理 <p> 标签结尾多余空格
// 输出结果
// var_dump($strNeiRong);
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel").'/novel/biquxs/'.$intFenleiId.'/'.$intXiaoShuoSourceID.'/'.$strZhangJieSourceId.'.txt';
//$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']) ;
} else {
var_dump("Error: " . $result['message']) ;
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoSourceID,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
];
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
unset($ZhangJieQueryList);
// 延时 3 秒
//sleep(3);
} catch (\Throwable $T) {
throw $T;
}
}
}

View File

@@ -1,498 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\dadi;
use app\model\VideoPlayurlModel;
use app\model\VideoLeixinModel;
use app\model\VideoDiquModel;
use app\model\VideoYearsModel;
use app\model\VideoJuqingModel;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\VideoInfoModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class DaDiDianyingCol extends PullDataColBase
{
public function pullDadiYingshi()
{
$TaskCore = $this->TaskCore;
// 1-75
for ($i = 1; $i <= 75; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => 'https://www.czdadi.net/vodshow/dy--------'.$i.'---.html',
'video_class_id' => 1
]
];
$TaskCore->set($arrTask);
}
//5-25 https://www.czdadi.net/vodshow/duanju-----------.html
for ($i = 1; $i <= 25; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => 'https://www.czdadi.net/vodshow/duanju--------'.$i.'---.html',
'video_class_id' => 5
]
];
$TaskCore->set($arrTask);
}
// 2--18 https://www.czdadi.net/vodshow/dsj--------18---.html
for ($i = 1; $i <= 18; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => 'https://www.czdadi.net/vodshow/dsj--------'.$i.'---.html',
'video_class_id' => 2
]
];
$TaskCore->set($arrTask);
}
// 3--11 https://www.czdadi.net/vodshow/zy--------11---.html
for ($i = 1; $i <= 11; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => 'https://www.czdadi.net/vodshow/zy--------'.$i.'---.html',
'video_class_id' => 3
]
];
$TaskCore->set($arrTask);
}
// 4--29 https://www.czdadi.net/vodshow/dm-----------.html
for ($i = 1; $i <= 29; $i++) {
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => 'https://www.czdadi.net/vodshow/dm--------'.$i.'---.html',
'video_class_id' => 4
]
];
$TaskCore->set($arrTask);
}
}
# 获取分页里面的视频列表
public function getVideoPage($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strUrl= $arrData['video_page_url'];
$intClassId = $arrData['video_class_id'];
$strSiteUrl = $this->get5cccDomain();
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
//$arrVideo = [];
// 检查是否找到元素
if ($QueryList->find('.stui-vodlist li .stui-vodlist__detail a')->count() > 0) {
$QueryList->find('.stui-vodlist li .stui-vodlist__detail a ')->map(function ($Video) use (&$arrVideo,$intClassId,&$TaskCore) {
// $arrVideo[] = [
// 'mingzi' => $Video->text(),
// 'url' => $Video->attr('href'),
// ];
if(!empty($Video->text()) && !empty($Video->attr('href'))){
$arrTask = [
'callback' => [self::class, 'getVideoInfo'],
'data' => [
'class_id' => $intClassId,
'video_href' => $Video->attr('href'),
'video_name' => $Video->text(),
]
];
$TaskCore->set($arrTask);
echo "视频投递成功 : " . $Video->text() . PHP_EOL;
}
});
// foreach ($arrVideo as $intVideoNum => $arrVideoOne) {
// $arrTask = [
// 'callback' => [self::class, 'getVideoInfo'],
// 'data' => [
// 'class_id' => $intClassId,
// 'video_href' => $arrVideoOne['url'],
// 'video_name' => $arrVideoOne['mingzi'],
// ]
// ];
// $TaskCore->set($arrTask);
// }
// 输出最终结果
// var_dump($arrVideo);
} else {
echo "No elements found for .stui-vodlist a" . PHP_EOL;
}
}
public function getVideoInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->getDadiDomain();
$strUrl = $strSiteUrl . $arrData['video_href'] ;
$intClassId = $arrData['class_id'];
$strVideoName = $arrData['video_name'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
$strCover = $QueryList->find('.stui-content__thumb img')->eq(0)->attr("data-original");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
// try {
// $strCoverUri = "";
// $strCoverUri = ImageProcessor::getInstance()->downloadImage( $intXiaoShuoSourceId,$strCover, 'dadi');
// } catch (\Throwable $t) {
// $strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
// echo $strErr;
// }
$arrCover = [
'code' => 'DADI_YINGSHI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strLanguage = "";
// if (strlen($strLanguage) > 0) {
// VideoLeixinModel::addVideoLeixin(['vc_id' => $intClassId, 'vla_name' => $strLanguage]);
// }
// 提取评分
$strPinfen = $QueryList->find('h1.title .score')->text();
// 提取类型-入库
$strLeixin = $QueryList->find('.col-pd a')->eq(1)->text();
if(strlen($strLeixin) > 0){
VideoLeixinModel::addVideoLeixin(['vc_id'=>$intClassId,'vl_name'=>$strLeixin]);
}
// 提取 HTML 的第一段 <p class="data">
$dataNode = $QueryList->find('p.data')->eq(0);
// 提取“类型”内容:确保只匹配 `href` 中包含 `/vodsearch/----`
$leixinNodes = $dataNode->find('a[href^="/vodsearch/----"]');
$strJuqing = $leixinNodes->map(function ($node) {
return $node->text();
})->all();
// 提取“地区”内容:确保只匹配 `href` 中包含 `/vodsearch/--`,但不包含 `/vodsearch/----`
$diquNodes = $dataNode->find('a[href^="/vodsearch/--"]')->not('a[href^="/vodsearch/----"]');
$strDiqu = $diquNodes->map(function ($node) {
return $node->text();
})->all();
// 提取“年份”内容:确保只匹配 `href` 中包含 `/vodsearch/-------------`
$yearsNode = $dataNode->find('a[href^="/vodsearch/-------------"]');
$strYears = $yearsNode->text();
if (!empty(trim($strYears))) {
$strYears = [trim($strYears)];
} else {
$strYears = [];
}
// 过滤掉“地区”和“年份”中的数据
$strJuqing = array_filter($strJuqing, function ($value) use ($strDiqu, $strYears) {
return !in_array($value, array_merge($strDiqu, $strYears));
});
// **在过滤后将“类型”数据入库**
foreach ($strJuqing as $value) {
if(strlen($value) > 0){
VideoJuqingModel::add(['vc_id' => $intClassId, 'vj_name' => $value]);
}
}
// 将“地区”数据入库
foreach ($strDiqu as $value) {
if(strlen($value) > 0){
VideoDiquModel::add(['vc_id' => $intClassId, 'vd_name' => $value]);
}
}
// 将“年份”数据入库
foreach ($strYears as $value) {
if(strlen($value) > 0){
VideoYearsModel::add(['vc_id' => $intClassId, 'vy_name' => $value]);
}
}
// 提取主演
$strZhuyan = $QueryList->find('p.data:contains("主演") a')->map(function ($item) {
return $item->text();
})->implode(', '); // 使用逗号分隔主演
// 提取导演
$strDaoyan = $QueryList->find('p.data:contains("导演") a')->map(function ($item) {
return $item->text();
})->implode(', '); // 使用逗号分隔主演
// 提取更新时间
$strLastDate = $QueryList->find('p.data.hidden-sm:contains("更新")')->text();
// 去掉“更新:”前缀
$strLastDate = str_replace('更新:', '', $strLastDate);
// 提取简介
$strDescription = $QueryList->find('#desc>.stui-pannel-box>.stui-pannel_bd>.col-pd')->text();
// 角标
$strJiaoBiao = $QueryList->find('.stui-content__thumb .text-right')->eq(0)->text();
$strPinyinId = extractFilename($strUrl);
$arrVideoInfo = [
'v_name' => $strVideoName,
'v_cover' => json_encode($arrCover),
'vc_id' => $intClassId,
'v_pinyin' => $strPinyinId,
'v_leixin' => $strLeixin ,
'v_juqing' => implode(', ', $strJuqing),
'v_diqu' => implode(', ', $strDiqu),
'v_years' => implode(', ', $strYears),
'v_language' => $strLanguage,
'v_daoyan' => $strZhuyan,
'v_zhuyan' => $strDaoyan,
'update_time' => $strLastDate,
'v_description'=>$strDescription,
'v_pingfen' => $strPinfen,
'v_orurl' => $strUrl,
'v_jiaobiao'=> $strJiaoBiao,
'v_md5' => md5($intClassId.$strVideoName.$strSiteUrl.$strUrl),
];
$VideoInfoModel = VideoInfoModel::addVideoXiangQing($arrVideoInfo);
$intVid = $VideoInfoModel->v_id;
$intChapterIndex = 0 ;
$arrZhangjie = [];
// // 检查是否找到元素
if ($QueryList->find('.stui-content__playlist a')->count() > 0) {
$QueryList->find('.stui-content__playlist a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex ,&$intVid) {
//echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
$arrZhangjie[] = [
'v_id' => $intVid,
'index' => $intChapterIndex,
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
$intChapterIndex++;
});
//var_dump($arrZhangjie);
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
// if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
// var_dump("小说章节已经入库,不再推送任务");
// continue;// 如果任务已存在,直接跳过 break
// }
//if($intZhangJieNum<=3){
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'v_id' => $intVid,
'vp_sort' => $intZhangJieNum,
'vp_name' => $arrZhangjieOne['mingzi'],
'vp_url' => $strSiteUrl . $arrZhangjieOne['url']
]
];
$TaskCore->set($arrTask);
//}
}
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
} catch (\Throwable $T) {
throw $T;
}
// sleep(10);
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
if (Cache::has('video_no_m3u8_' . $arrData['v_id'])) {
echo "跳过抓取视频ID已在缓存中: " . $arrData['v_id'] . "\n";
return; // 跳过抓取逻辑
}
$strMuluHref = $arrData['vp_url'];
var_dump($strMuluHref);
$Client = $this->Client;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strMuluHref);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strMuluHref, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$QueryList = QueryList::html($strResult);
//提取 <script> 标签内容
$scriptContent = $QueryList->find('.vidoe-data-show')->text();
$strM3u8Url = "";
// 使用正则表达式提取 "url" 的值
if (preg_match('/"url":"(https:[^"]+\.m3u8)"/', $scriptContent, $matches)) {
$strM3u8Url = str_replace('\/', '/', $matches[1]); // 替换转义斜杠
echo "提取的 M3U8 地址: $strM3u8Url\n";
$arrM3u8Url = [
'code' => 'DADI_YINGSHI_M3U8',
'uri' => $strM3u8Url,
];
$arrVideoPlayurl = [
'v_id' => $arrData['v_id'],
'vp_sort' => $arrData['vp_sort'],
'vp_name' => $arrData['vp_name'],
'vp_url' => json_encode($arrM3u8Url),
'vp_md5' => md5($arrData['vp_url'] . $arrData['vp_url']),
];
VideoPlayurlModel::add($arrVideoPlayurl);
unset($QueryList);
} else {
echo "未找到 M3U8 地址\n";
// 将视频ID保存到缓存设置一个过期时间例如 1 小时
Cache::set('video_no_m3u8_' . $arrData['v_id'], true, 3600);
}
} catch (\Throwable $T) {
throw $T;
}
}
}

View File

@@ -1,560 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\heimuer;
use app\model\VideoPlayurlModel;
use app\model\VideoLeixinModel;
use app\model\VideoDiquModel;
use app\model\VideoYearsModel;
use app\model\VideoJuqingModel;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\VideoInfoModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class HeiMuErYingShiCol extends PullDataColBase
{
public function pullDadiYingshi()
{
$strSiteUrl = $this->getHeiMuErDomain();
// 配置分类任务参数
$categories = [
['id' => 1, 'video_class_id' => 1, 'name' => '电影'],
['id' => 27, 'video_class_id' => 5, 'name' => '短剧'],
['id' => 2, 'video_class_id' => 2, 'name' => '电视剧'],
['id' => 4, 'video_class_id' => 3, 'name' => '综艺'],
['id' => 3, 'video_class_id' => 4, 'name' => '动漫'],
];
foreach ($categories as $category) {
$intClassId = $category['video_class_id'];
$intCategoryId = $category['id'];
// 先抓第一页
$strUrl = $strSiteUrl . '/index.php/vod/type/id/' . $intCategoryId . '/page/1.html';
$maxPage = $this->getMaxPage($strUrl,$intClassId);
// 首次抓取,全部抓取
if (config('task.task_is_first')) {
$this->createTasks($strSiteUrl, $category['id'], $category['video_class_id'], $maxPage);
}
}
}
/**
* 获取分类的最大页码且抓取第一页
*/
protected function getMaxPage($strUrl, $intClassId)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'en-US,en;q=0.5',
'cookie' => '__sk_Vm8nTqM7LqSCWmR6__=be3bd4f4e0483619e1a434ec1b18a938',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 300,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// 检查是否找到元素
if ($QueryList->find('.stui-vodlist li.clearfix h3 a')->count() > 0) {
$QueryList->find('.stui-vodlist li.clearfix h3 a ')->map(function ($Video) use ($intClassId, &$TaskCore) {
$strHref = $Video->attr('href');
$strName = $Video->text();
if (!empty($strName) && !empty($strHref) && strlen($strName) > 0 && strlen($strHref) > 0) {
$arrTask = [
'callback' => [self::class, 'getVideoInfo'],
'data' => [
'class_id' => $intClassId,
'video_href' => $strHref,
'video_name' => $strName,
]
];
// var_dump($arrTask);
$TaskCore->set($arrTask);
echo "视频投递成功 : " . $Video->text() . PHP_EOL;
}
});
} else {
echo "No elements found for .stui-vodlist a" . PHP_EOL;
}
// 获取分页部分最后一个页码链接
$lastPageHref = $QueryList->find('.stui-page li')->eq($QueryList->find('.stui-page li')->count() - 1)->find('a')->attr('href');
// 提取最大页码
preg_match('/page\/(\d+)\.html/', $lastPageHref, $matches);
$maxPage = isset($matches[1]) ? (int)$matches[1] : 1; // 默认返回 1
return $maxPage;
}
/**
* 创建任务
*/
protected function createTasks($strSiteUrl, $categoryId, $videoClassId, $maxPage)
{
$TaskCore = $this->TaskCore;
for ($i = $maxPage; $i >= 1; $i--) {
echo "当前分类: $categoryId, 当前页: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/' . $categoryId . '/page/' . $i . '.html',
'video_class_id' => $videoClassId,
]
];
$TaskCore->set($arrTask);
}
}
# 获取分页里面的视频列表
public function getVideoPage($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strUrl = $arrData['video_page_url'];
$intClassId = $arrData['video_class_id'];
$strSiteUrl = $this->getHeiMuErDomain();
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
var_dump($strUrl);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'en-US,en;q=0.5',
'cookie' => '__sk_Vm8nTqM7LqSCWmR6__=be3bd4f4e0483619e1a434ec1b18a938',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 300,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// 检查是否找到元素
if ($QueryList->find('.stui-vodlist li.clearfix h3 a')->count() > 0) {
$QueryList->find('.stui-vodlist li.clearfix h3 a ')->map(function ($Video) use (&$arrVideo, $intClassId, &$TaskCore, $strSiteUrl) {
$strHref = $Video->attr('href');
$strName = $Video->text();
if (!empty($strName) && !empty($strHref) && strlen($strName) > 0 && strlen($strHref) > 0) {
$arrTask = [
'callback' => [self::class, 'getVideoInfo'],
'data' => [
'class_id' => $intClassId,
'video_href' => $strHref,
'video_name' => $strName,
]
];
// var_dump($arrTask);
$TaskCore->set($arrTask);
echo "视频投递成功 : " . $Video->text() . PHP_EOL;
}
});
} else {
echo "No elements found for .stui-vodlist a" . PHP_EOL;
}
}
public function getVideoInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->getHeiMuErDomain();
$strUrl = $strSiteUrl . $arrData['video_href'];
$intClassId = $arrData['class_id'];
$strVideoName = $arrData['video_name'];
var_dump($strUrl);
if (!empty($strVideoName) && !empty($strUrl) && strlen($strVideoName) > 0 && strlen($strUrl) > 0) {
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
$strCover = $QueryList->find('.img-responsive')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
// try {
// $strCoverUri = "";
// $strCoverUri = ImageProcessor::getInstance()->downloadImage( $intXiaoShuoSourceId,$strCover, 'dadi');
// } catch (\Throwable $t) {
// $strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
// echo $strErr;
// }
$arrCover = [
'code' => 'HEIMUER_SOURCE_COVER',
'uri' => $strCoverUri,
];
$strLanguage = "";
// if (strlen($strLanguage) > 0) {
// VideoLeixinModel::addVideoLeixin(['vc_id' => $intClassId, 'vla_name' => $strLanguage]);
// }
// 提取别名
$strPinyinId = $QueryList->find('.stui-content__detail p.data')->eq(0)->text();
// 提取评分
$strPinfen = $QueryList->find('.stui-content__detail h1 .text-red')->text();
// 提取地区
$strDiqu = $QueryList->find('.stui-content__detail p.data')->eq(1)->text();
// 角标-状态
$strJiaoBiao = $QueryList->find('.stui-content__detail p.data')->eq(2)->find('.text-red')->eq(0)->text();
// 更新时间
$strLastDate = $QueryList->find('.stui-content__detail p.data')->eq(2)->find('.text-red')->eq(1)->text();
// 提取主演
$strZhuyan = $QueryList->find('.stui-content__detail p.data')->eq(3)->text();
// 提取导演
$strDaoyan = $QueryList->find('.stui-content__detail p.data')->eq(4)->text();
// 提取
$arrLeixinData = $QueryList->find('.stui-content__detail p.data')->eq(5)->text();
// 提取
$arrYuyanData = $QueryList->find('.stui-content__detail p.data')->eq(6)->text();
$strLeixin = '';
$strDiqu = '';
$strYears = '';
$strKuozhang = '';
// 使用正则表达式提取内容
$patternLeixin = '/类型:(.*?)扩展:(.*?)地区:(.*?)年份:(.*)/';
if (preg_match($patternLeixin, $arrLeixinData, $matches)) {
$strLeixin = trim($matches[1]);
$strKuozhang = trim($matches[2]);
$strDiqu = trim($matches[3]);
$strYears = trim($matches[4]);
}
$strLanguage = '';
// 使用正则表达式提取内容
$patternYuyan = '/语言:(.*?)集数:(.*?)时长:(.*?)点击:(.*)/';
if (preg_match($patternYuyan, $arrYuyanData, $matches)) {
$strLanguage = trim($matches[1]);
// $strKuozhang = trim($matches[2]);
// $strDiqu = trim($matches[3]);
// $strYears = trim($matches[4]);
}
if (strlen($strLeixin) > 0) {
VideoLeixinModel::addVideoLeixin(['vc_id' => $intClassId, 'vl_name' => $strLeixin]);
}
if (strlen($strDiqu) > 0) {
VideoDiquModel::add(['vc_id' => $intClassId, 'vd_name' => $strDiqu]);
}
if (strlen($strYears) > 0) {
VideoYearsModel::add(['vc_id' => $intClassId, 'vy_name' => $strYears]);
}
// 提取简介
$strDescription = $QueryList->find('.stui-content__desc')->text();
$arrVideoInfo = [
'v_name' => $strVideoName,
'v_cover' => json_encode($arrCover),
'vc_id' => $intClassId,
'v_pinyin' => trim(str_replace('别名:', '', $strPinyinId)),
'v_leixin' => $strLeixin,
'v_juqing' => '',
'v_diqu' => $strDiqu,
'v_years' => $strYears,
'v_language' => $strLanguage,
'v_daoyan' => trim(str_replace('主演:', '', $strZhuyan)),
'v_zhuyan' => trim(str_replace('导演:', '', $strDaoyan)),
'update_time' => $strLastDate,
'v_description' => $strDescription,
'v_pingfen' => $strPinfen,
'v_orurl' => $strUrl,
'v_jiaobiao' => $strJiaoBiao,
'v_md5' => md5($intClassId . $strVideoName . getUriByUrl($strUrl)),
];
//var_dump($arrVideoInfo);
// // 检查是否找到元素
if ($QueryList->find('.stui-content__playlist li')->count() > 0) {
// var_dump("视频入库成功--" . $strVideoName);
// $VideoInfoModel = VideoInfoModel::addVideoXiangQing($arrVideoInfo);
$resultVideoInfoModel = VideoInfoModel::addVideoXiangQing($arrVideoInfo);;
if ($resultVideoInfoModel['isNew']) {
var_dump("数据已新增:", $resultVideoInfoModel['model']->v_id."视频入库成功--" . $strVideoName);
} else {
echo "数据已存在:", $resultVideoInfoModel['model']->v_id;
}
$VideoInfoModel = $resultVideoInfoModel['model'];
$intVid = $VideoInfoModel->v_id;
$intChapterIndex = 0;
$QueryList->find('.stui-content__playlist li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex, &$intVid) {
//echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
$strM3u8 = $ZhangJie->find('a')->eq(1)->text();
$arrM3u8 = explode('$', $strM3u8);
$strM3u8Url = $arrM3u8[1];
$strM3u8Name = $arrM3u8[0];
$arrM3u8Url = [
'code' => 'HEIMUER_SOURCE_PLAY',
'uri' => $strM3u8Url,
];
$arrVideoPlayurl = [
'v_id' => $intVid,
'vp_sort' => $intChapterIndex,
'vp_name' => $strM3u8Name,
'vp_url' => json_encode($arrM3u8Url),
'vp_md5' => md5($intVid . getUriByUrl($strM3u8Url)),
];
$result = VideoPlayurlModel::add($arrVideoPlayurl);;
if ($result['isNew']) {
var_dump("数据已新增:", $result['model']->vp_id."播放线路入库成功--" . $strM3u8Url) ;
} else {
echo "数据已存在:", $result['model']->vp_id ;
}
$intChapterIndex++;
});
var_dump("--") ;
var_dump("一个视频任务完成------------------------------------------------------------------------------------") ;
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
} catch (\Throwable $T) {
throw $T;
}
}
// sleep(10);
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
$strMuluHref = $arrData['vp_url'];
var_dump($strMuluHref);
$Client = $this->Client;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strMuluHref);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strMuluHref, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$QueryList = QueryList::html($strResult);
//提取 <script> 标签内容
$scriptContent = $QueryList->find('.vidoe-data-show')->text();
$strM3u8Url = "";
// 使用正则表达式提取 "url" 的值
if (preg_match('/"url":"(https:[^"]+\.m3u8)"/', $scriptContent, $matches)) {
$strM3u8Url = str_replace('\/', '/', $matches[1]); // 替换转义斜杠
echo "提取的 M3U8 地址: $strM3u8Url\n";
$arrM3u8Url = [
'code' => 'DADI_YINGSHI_M3U8',
'uri' => $strM3u8Url,
];
$arrVideoPlayurl = [
'v_id' => $arrData['v_id'],
'vp_sort' => $arrData['vp_sort'],
'vp_name' => $arrData['vp_name'],
'vp_url' => json_encode($arrM3u8Url),
'vp_md5' => md5($arrData['vp_url'] . $arrData['vp_url']),
];
VideoPlayurlModel::add($arrVideoPlayurl);
unset($QueryList);
} else {
echo "未找到 M3U8 地址\n";
}
} catch (\Throwable $T) {
throw $T;
}
}
public function pullDadiYingshi2()
{
$strSiteUrl = $this->getHeiMuErDomain();
$TaskCore = $this->TaskCore;
//电影 307 https://heimuer.tv/index.php/vod/type/id/1/page/307.html
for ($i = 307; $i >= 1; $i--) {
if (!config('task.task_is_first') && $i > 1) {
continue;
}
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/1/page/' . $i . '.html',
'video_class_id' => 1
]
];
$TaskCore->set($arrTask);
}
//5-87 短剧 https://heimuer.tv/index.php/vod/type/id/27/page/87.html
for ($i = 87; $i >= 1; $i--) {
if (!config('task.task_is_first') && $i > 1) {
continue;
}
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/27/page/' . $i . '.html',
'video_class_id' => 5
]
];
$TaskCore->set($arrTask);
}
//电视剧 2--225 https://heimuer.tv/index.php/vod/type/id/2/page/225.html
for ($i = 225; $i >= 1; $i--) {
if (!config('task.task_is_first') && $i > 1) {
continue;
}
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/2/page/' . $i . '.html',
'video_class_id' => 2
]
];
$TaskCore->set($arrTask);
}
//综艺 78 https://heimuer.tv/index.php/vod/type/id/4/page/78.html
for ($i = 78; $i >= 1; $i--) {
if (!config('task.task_is_first') && $i > 1) {
continue;
}
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/4/page/' . $i . '.html',
'video_class_id' => 3
]
];
$TaskCore->set($arrTask);
}
// 动漫--100 https://heimuer.tv/index.php/vod/type/id/3/page/1.html
for ($i = 100; $i >= 1; $i--) {
if (!config('task.task_is_first') && $i > 1) {
continue;
}
echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/index.php/vod/type/id/3/page/' . $i . '.html',
'video_class_id' => 4
]
];
$TaskCore->set($arrTask);
}
}
}

View File

@@ -1,850 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\novel;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\model\NovelInfoSeoModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
use app\common\Base64Helper as qsbs;
/**
* @mixin think\Model https://www.630zw.org/
*/
class Zw630XiaoShuoCol extends PullDataColBase
{
public function pullXiaoShuo()
{
// $decoded = '美女';
// $encoded = qsbs::encode($decoded);
// $decodedString = qsbs::decode('5oC75LmL77yM57uT5bGA5piv5aW955qE77yM5amJ5YS/5bqU6K+l5LiN5Lya5Zyo5LmO6L+Z5Lqb57uG6IqC44CCPC9wPg==');
// var_dump($encoded);
// var_dump($decodedString);
// 首次抓取,全部抓取
if (config('task.task_is_first')) {
$TaskCore = $this->TaskCore;
// 527797
for ($i = config('task.task_start_number'); $i <= config('task.task_end_number'); $i++) {
//echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_source_id' => $i, //528049
'xs_source_seo_id' => 1,
]
];
$TaskCore->set($arrTask);
// var_dump($arrTask);
}
}else{
$this->pullFenlei();
}
}
public function pullFenlei()
{
$TaskCore = $this->TaskCore;
for ($intFenleiId = 1; $intFenleiId <= 9; $intFenleiId++) {
for ($intPage = 1; $intPage <= 10; $intPage++) {
// https://www.630zw.org/list/1/10.html
$arrTask = [
'callback' => [self::class, 'getFenLei'],
'data' => [
'xs_fenlei_url' => 'https://www.630zw.org/list/'.$intFenleiId.'/'.$intPage.'.html',
]
];
$TaskCore->set($arrTask);
// var_dump($arrTask);
}
}
}
public function getFenLei($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->get630zwDomain();
$strUrl = $arrData['xs_fenlei_url']; //1 ;
var_dump($strUrl);
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
$arrNovel = [];
// 检查是否找到元素
if ($QueryList->find('.layout2 .txt-list-row5')->eq(0)->find('li')->count() > 0) {
$QueryList->find('.layout2 .txt-list-row5')->eq(0)->find('li')->map(function ($Novel) use (&$arrNovel) {
$strNovelHref = $Novel->find('.s2 a')->attr('href') ;
$intNovelId = extractFilename($strNovelHref);
var_dump($strNovelHref);
$arrNovel[] = [
'xs_source_id' => $intNovelId, //528049
'xs_source_seo_id' => 1,
];
});
} else {
echo 'qie h5' . PHP_EOL;
if ($QueryList->find('.sort_list')->eq(0)->find('li')->count() > 0) {
$QueryList->find('.sort_list')->eq(0)->find('li')->map(function ($Novel) use (&$arrNovel) {
$strNovelHref = $Novel->find('.s2 a')->attr('href') ;
$intNovelId = extractFilename($strNovelHref);
var_dump($strNovelHref);
$arrNovel[] = [
'xs_source_id' => $intNovelId, //528049
'xs_source_seo_id' => 1,
];
});
}
}
foreach ($arrNovel as $intNum => $arrNovelOne) {
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => $arrNovelOne,
];
$TaskCore->set($arrTask);
}
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getFenLei'],
'data' => [
'xs_fenlei_url' => $strUrl,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
public function getNovelInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->get630zwDomain();
$strUrl = 'https://630zw.org/shu/' . $arrData['xs_source_id'] . '.html'; //'https://630zw.org/shu/93716.html';
$intXiaoShuoSourceId = $arrData['xs_source_id']; //20053;
$intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id']; //1 ;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// var_dump($QueryList);
// 提取所有 <meta> 标签的属性
$result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
return [
'property' => $item->attr('property'),
'content' => $item->attr('content'),
];
});
// 打印结果
// print_r($result->all());
$strZuoZhe = '';
$strMingZi = '';
$strLastDate = '';
$strJieShao = '';
$strCover = '';
$strFenlei = '';
$strZiShu = 0;
$strZhuangTai = '';
foreach ($result as $item) {
switch ($item['property']) {
case 'og:title':
$strMingZi = $item['content'];
break;
case 'og:description':
$strJieShao = preg_split('/<br\s*\/?>/i', $item['content'])[0];
break;
case 'og:image':
$strCover = $item['content'];
break;
case 'og:novel:category':
$strFenlei = $item['content'];
break;
case 'og:novel:author':
$strZuoZhe = $item['content'];
break;
case 'og:novel:status':
$strZhuangTai = $item['content'];
break;
case 'og:novel:update_time':
$strLastDate = $item['content'];
break;
}
}
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadImage($intXiaoShuoSourceId, $strCover, 'xs/630zw');
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
$arrCover = [
'code' => '630_ZW_XS_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strFenleiIId = 1;
switch ($strFenlei) {
case '玄幻修真':
$strName = "玄幻";
$strFenleiIId = 1;
break;
case '重生穿越':
$strName = "修真";
$strFenleiIId = 2;
break;
case '都市小说':
$strName = "都市";
$strFenleiIId = 3;
break;
case '军史小说':
$strName = "历史";
$strFenleiIId = 4;
break;
case '网游小说':
$strName = "网游";
$strFenleiIId = 5;
break;
case '科幻小说':
$strName = "科幻";
$strFenleiIId = 6;
break;
case '灵异小说':
$strName = "女频";
$strFenleiIId = 7;
break;
case '言情小说':
$strName = "其它";
$strFenleiIId = 8;
break;
case '其他小说':
$strName = "其它";
$strFenleiIId = 9;
break;
default:
$strName = "其它";
$strFenleiIId = 9;
break;
}
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe, //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $strFenleiIId,
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceId . '1',
'xsxq_source_code' => 'ZW630_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::where('xsxq_source_code', $arrXiaoShuoInfo['xsxq_source_code'])->find();
$arrZhangjie = [];
# seo 小说入库 - 只有新小说才会走这个步骤
if (!$XiaoShuoXiangQingModel) {
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
$intXiaoShuolId = $XiaoShuoXiangQingModel->xsxq_id;
// 检查是否找到元素-seo 小说入库
if ($QueryList->find('.first_txt a')->count() > 0 && $intXiaoShuolId) {
$QueryList->find('.first_txt a')->map(function ($ZhangJie) use ($intXiaoShuolId) {
$url = $ZhangJie->attr('href');
// 检查是否以 "/kan/" 开头
if (strpos($url, '/kan/') === 0) { // strpos 返回位置0 表示是以 "/kan/" 开头
// 处理符合条件的链接
// echo "Processing index : " . $ZhangJie->text() . PHP_EOL;
$arrXiaoShuoSeoInfo = [
'nis_name' => $ZhangJie->text(),
'xsxq_id' => $intXiaoShuolId,
'nis_md5' => md5($intXiaoShuolId . $ZhangJie->text()),
];
NovelInfoSeoModel::addXiaoShuoXiangQingSeo($arrXiaoShuoSeoInfo);
}
});
} else {
echo "No elements found for .first_txt a" . PHP_EOL;
var_dump($strResult);
}
// # 新小说全部章节入库
// $intChapterIndex = 1; // 定义一个计数器变量
// // 检查是否找到元素
// if ($QueryList->find('.section-list')->eq(1)->find('li')->count() > 0) {
// $QueryList->find('.section-list')->eq(1)->find('li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
// echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// $arrZhangjie[] = [
// 'paixu' => $intChapterIndex,
// 'mingzi' => $ZhangJie->find('a')->text(),
// 'url' => $ZhangJie->find('a')->attr('href'),
// ];
// $intChapterIndex++;
// });
// } else {
// echo "No elements found for .listmain a" . PHP_EOL;
// }
//unset($QueryList);
}else{
$intXiaoShuolId = $XiaoShuoXiangQingModel->xsxq_id;
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuolId)
->max('xszj_pai_xu'); // 获取最大值
// var_dump('获取小说章节最大值-'.$intMaxXiaoShuoZhangJiePaixu);
}
# 新小说全部章节入库
$intChapterIndex = 1; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryList->find('.section-list')->eq(1)->find('li')->count() > 0) {
$QueryList->find('.section-list')->eq(1)->find('li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
// echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
$arrZhangjie[] = [
'paixu' => $intChapterIndex,
'mingzi' => $ZhangJie->find('a')->text(),
'url' => $ZhangJie->find('a')->attr('href'),
];
$intChapterIndex++;
});
$this->eachNovelReader($arrZhangjie,$strSiteUrl,$intXiaoShuolId,$strFenleiIId);
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
# 章节处理
# 新小说全部章节入库
# 旧小说,只更新最新章节,获取数据库最大章节索引,对比源总章节
// // 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
# 目录页面处理
$strMuluHref = $QueryList->find('.btn-mulu')->eq(0)->attr('href');
$strMuluHref = $strSiteUrl . $strMuluHref ;
$ResponseMulu = $Client->request('GET', $strMuluHref, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResultMulu = (string)$ResponseMulu->getBody();
$QueryListMulu = QueryList::html($strResultMulu);
$intMuluTotal = $QueryListMulu->find('.page_num select')->eq(0)->find('option')->count();
$strMuluEndHref = $QueryListMulu->find('.page_num select')->eq(0)->find('option')->eq($intMuluTotal-1)->attr('value');
$strMuluEndText = $QueryListMulu->find('.page_num select')->eq(0)->find('option')->eq($intMuluTotal-1)->text();
// 使用正则表达式匹配
preg_match_all('/\.section-list\.ycxsid>li:nth-child\(/', $strResultMulu, $matches);
preg_match_all('/\.section-list\.ycxsid>li:nth-last-child\(/', $strResultMulu, $matchesLast);
$intProLiNum = count($matches[0]);
$intLastLiNum = count($matchesLast[0]);
$arrZhangjieMulu = [];
//if($intMaxXiaoShuoZhangJiePaixu < 200){
$intChapterPageIndex = 101; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryListMulu->find('.chapter-list')->eq(0)->find('li')->count() > 0) {
$QueryListMulu->find('.chapter-list')->eq(0)->find('li')->map(function ($ZhangJie) use (&$arrZhangjieMulu, &$intChapterPageIndex) {
$arrZhangjieMulu[] = [
'paixu' => $intChapterPageIndex,
'mingzi' => $ZhangJie->find('a')->text(),
'url' => $ZhangJie->find('a')->attr('href'),
];
$intChapterPageIndex ++ ;
});
$arrZhangjieMulu = array_slice($arrZhangjieMulu, $intProLiNum);
// 删除后 11 条数据
$arrZhangjieMulu = array_slice($arrZhangjieMulu, 0, count($arrZhangjieMulu) - $intLastLiNum);
$this->eachNovelReader($arrZhangjieMulu,$strSiteUrl,$intXiaoShuolId,$strFenleiIId);
var_dump("chapter章节任务投递成功 $strMuluHref");
} else {
// var_dump($QueryListMulu->find('.section-list')->eq(0)->find('li')->count());
//echo "No elements found for .chapter-list $strMuluHref" . PHP_EOL;
// 检查是否找到元素
$intListIndex = 1;
if ($QueryListMulu->find('.section-list')->eq(0)->find('li')->count() > 0) {
$QueryListMulu->find('.section-list')->eq(0)->find('li')->map(function ($ZhangJie) use (&$arrZhangjieMulu, &$intChapterPageIndex,&$intListIndex) {
if($intListIndex >14){
$arrZhangjieMulu[] = [
'paixu' => $intChapterPageIndex,
'mingzi' => $ZhangJie->find('a')->text(),
'url' => $ZhangJie->find('a')->attr('href'),
];
$intChapterPageIndex ++ ;
};
$intListIndex++ ;
});
$arrZhangjieMulu = array_slice($arrZhangjieMulu, $intProLiNum);
// 删除后 11 条数据
$arrZhangjieMulu = array_slice($arrZhangjieMulu, 0, count($arrZhangjieMulu) - $intLastLiNum);
$this->eachNovelReader($arrZhangjieMulu,$strSiteUrl,$intXiaoShuolId,$strFenleiIId);
var_dump("section章节任务投递成功 $strMuluHref");
} else {
var_dump("No elements found for .section-list $strMuluHref") ;
}
}
//}
// 输出最终结果
// var_dump(count($arrZhangjie));
// var_dump($QueryListMulu->find('.chapter-list li')->count());
// var_dump($intMuluTotal);
// var_dump($strMuluEndHref);
// var_dump($strMuluEndText);
// var_dump($intMaxXiaoShuoZhangJiePaixu); // 1010
preg_match('/(\d+)-(\d+)章/', $strMuluEndText, $matches);
$intMaxPaixu = $matches[2]; // 最大章节
$intMaxMuluPage = floor($intMaxPaixu / 100); // 最大目录页面
// $intMaxMuluPage = 2;
// 所有目录分页处理
for ($i = 2; $i <= $intMaxMuluPage; $i++) {
//echo "当前值: $i\n";
$arrTask = [
'callback' => [self::class, 'getNovelMulu'],
'data' => [
'strMuluHref' => $strSiteUrl . '/shu/' . $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $i . '.html' ,
'xsxq_id' => $XiaoShuoXiangQingModel->xsxq_id,
'xsfl_id' => $strFenleiIId,
'intStartIndex' => $i*100 + 1,
]
];
$TaskCore->set($arrTask);
// var_dump($arrTask);
}
unset($QueryList);
unset($QueryListMulu);
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_source_id' => $arrData['xs_source_id'],
'xs_source_seo_id' => $intXiaoShuoSourceSeoId,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
public function getNovelMulu($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->get630zwDomain();
$strUrl = $arrData['strMuluHref'];
$intXiaoShuoId = $arrData['xsxq_id'];
$intXiaoShuoFenleiId = $arrData['xsfl_id'];
$intStartIndex = $arrData['intStartIndex'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// 使用正则表达式匹配
preg_match_all('/\.section-list\.ycxsid>li:nth-child\(/', $strResult, $matches);
preg_match_all('/\.section-list\.ycxsid>li:nth-last-child\(/', $strResult, $matchesLast);
$intProLiNum = count($matches[0]);
$intLastLiNum = count($matchesLast[0]);
$arrZhangjie = [];
if ($QueryList->find('.chapter-list')->eq(0)->find('li')->count() > 0) {
$QueryList->find('.chapter-list')->eq(0)->find('li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intStartIndex) {
$arrZhangjie[] = [
'paixu' => $intStartIndex,
'mingzi' => $ZhangJie->find('a')->text(),
'url' => $ZhangJie->find('a')->attr('href'),
];
$intStartIndex ++ ;
// var_dump($intStartIndex);
});
$arrZhangjie = array_slice($arrZhangjie, $intProLiNum);
// 删除后 11 条数据
$arrZhangjie = array_slice($arrZhangjie, 0, count($arrZhangjie) - $intLastLiNum);
$this->eachNovelReader($arrZhangjie,$strSiteUrl,$intXiaoShuoId,$intXiaoShuoFenleiId);
var_dump("chapter章节任务投递成功 $strUrl");
} else {
// 检查是否找到元素
if ($QueryList->find('.section-list')->eq(0)->find('li')->count() > 0) {
$QueryList->find('.section-list')->eq(0)->find('li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intStartIndex) {
$arrZhangjie[] = [
'paixu' => $intStartIndex,
'mingzi' => $ZhangJie->find('a')->text(),
'url' => $ZhangJie->find('a')->attr('href'),
];
$intStartIndex ++ ;
// var_dump($intStartIndex);
});
$arrZhangjie = array_slice($arrZhangjie, $intProLiNum);
// 删除后 11 条数据
$arrZhangjie = array_slice($arrZhangjie, 0, count($arrZhangjie) - $intLastLiNum);
$this->eachNovelReader($arrZhangjie,$strSiteUrl,$intXiaoShuoId,$intXiaoShuoFenleiId);
var_dump("section章节任务投递成功 $strUrl");
} else {
var_dump("No elements found for .section-list $strUrl") ;
}
}
unset($QueryList);
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getNovelMulu'],
'data' => [
'strMuluHref' => $strUrl ,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intXiaoShuoFenleiId,
'intStartIndex' => $intStartIndex,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
public function eachNovelReader($arrZhangjie,$strSiteUrl,$intXiaoShuoId,$intXiaoShuoFenleiId)
{
$TaskCore = $this->TaskCore;
// var_dump($arrZhangjie);
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
// if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
// var_dump("小说章节已经入库,不再推送任务");
// continue;// 如果任务已存在,直接跳过 break
// }
$strZhangJieUrl = 'https://www.630zw.org' . $arrZhangjieOne['url'];
$strZhangJieSourceId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = '630ZW_XIAOSHUO_ZHANGJIE_'. $intXiaoShuoId . '_' . $strZhangJieSourceId . '_1' ;
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $arrZhangjieOne['paixu'],
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intXiaoShuoFenleiId,
'intZhangJieSort' => 1,
]
];
$TaskCore->set($arrTask);
}
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
//https://www.630zw.org/shu/438374/156339465.html
public function getNovelReader($arrData)
{
$TaskCore = $this->TaskCore;
$strSiteUrl = 'https://www.630zw.org';
var_dump('getNovelReader------------------------------------------------------------------------------------');
$Client = $this->Client;
$intZhangJieSort = $arrData['intZhangJieSort'];
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoId = $arrData['xsxq_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
$strZhangJieName = $arrData['xszj_name'];
$XiaoShuoZhangJieModel = XiaoShuoZhangJieModel::where('xszj_source_code', $strXszjSourceCode)->find();
if ($XiaoShuoZhangJieModel) {
var_dump($XiaoShuoZhangJieModel->xszj_source_code);
var_dump('章节已经存在 paixu: '.$intZhangJiePaiXu);
var_dump('章节已经存在strXszjSourceCode: '.$strXszjSourceCode);
var_dump('章节已经存在strZhangJieUrl: '.$strZhangJieUrl);
// return true;
}
var_dump($strZhangJieUrl);
var_dump('章节排序:'.$intZhangJiePaiXu);
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$ZhangJieQueryList = QueryList::html($strResult);
// 正则表达式,匹配 `_数字.html`
$pattern = '/_(\d+)\.html$/';
$patternHref = '/(\/shu\/\d+\/\d+_\d+\.html)/';
$strNeiRong = '';
$strNextHref = '';
// 使用 preg_match() 进行匹配
if (preg_match($patternHref, $strResult, $matches)) {
// 提取匹配到的部分
echo "提取到的 URL 是: " . $matches[1];
$strNextHref = $matches[1];
} else {
echo "没有匹配到 URL";
}
preg_match_all("/qsbs\.bb\('([^']+)'\)/", $strResult, $matches);
// 输出提取到的加密字符串
if (isset($matches[1])) {
$strNeiRong = implode(';;;', $matches[1]);
// var_dump($strNeiRong);
}
// 判断字符串是否匹配
if (preg_match($pattern, $strNextHref, $matches) ){
$intNextPage = 2;
// 确保匹配成功后再访问索引
if (isset($matches[1])) {
$intNextPage = (int)$matches[1];
$intNextPage +=1;
var_dump('提取到的数字是:' . $intNextPage);
}
var_dump('提取到的数字是-' . $intNextPage);
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJiePaiXu,
'xszj_name' => $strZhangJieName,
'xszj_url' => $strSiteUrl . $strNextHref,
'xszj_source_code' => '630ZW_XIAOSHUO_ZHANGJIE_'. $intXiaoShuoId . '_' . $strZhangJieSourceId . '_' . $intNextPage,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intFenleiId,
'intZhangJieSort' => $intNextPage,
]
];
$TaskCore->set($arrTask);
}
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel") . '/novel/630zwxs/' . $intFenleiId . '/' . $intXiaoShuoId .'/' . $intZhangJiePaiXu .'/' . $intZhangJieSort . '.txt';
//$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']);
} else {
var_dump("Error: " . $result['message']);
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoId,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
'xszj_sort' => $intZhangJieSort,
];
// var_dump($arrXiaoShuoZhangJie);
if($strZhangJieName){
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
}
unset($ZhangJieQueryList);
// // 延时 3 秒
//sleep(3);
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJiePaiXu,
'xszj_name' => $strZhangJieName,
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intFenleiId,
'intZhangJieSort' => $intZhangJieSort,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
}

View File

@@ -1,426 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\novelone;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use QL\QueryList;
use app\common\Base64Helper;
/**
* @ 抓取 gdbzkz.info 站点相关小说
*/
class NovelJiuYuFanXianCol extends PullDataColBase
{
public function pullXiaoShuo()
{
$TaskCore = $this->TaskCore;
// http://www.gdbzkz.info/jiuyufanxian/
$arrNovel = [
['xs_source_id' => 'jiuyufanxian'],
];
foreach ($arrNovel as $Novel) {
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_source_id' => $Novel['xs_source_id'],
'xs_source_seo_id' => 1,
]
];
$TaskCore->set($arrTask);
var_dump($arrTask);
}
}
public function getNovelInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = 'http://www.gdbzkz.info';
$intXiaoShuoSourceId = $arrData['xs_source_id'];
$intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id'];
$strUrl = $strSiteUrl . '/' . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// var_dump($QueryList);
// 提取所有 <meta> 标签的属性
$result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
return [
'property' => $item->attr('property'),
'content' => $item->attr('content'),
];
});
// 打印结果
// print_r($result->all());
$strZuoZhe = '';
$strMingZi = '';
$strLastDate = '';
$strJieShao = '';
$strCover = '';
$strFenlei = '';
$strZiShu = 0;
$strZhuangTai = '';
foreach ($result as $item) {
switch ($item['property']) {
case 'og:title':
$strMingZi = $item['content'];
break;
case 'og:description':
$strJieShao = $item['content'];
break;
case 'og:image':
$strCover = $item['content'];
break;
case 'og:novel:category':
$strFenlei = $item['content'];
break;
case 'og:novel:author':
$strZuoZhe = $item['content'];
break;
case 'og:novel:status':
$strZhuangTai = $item['content'];
break;
case 'og:novel:update_time':
$strLastDate = $item['content'];
break;
}
}
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadImage($intXiaoShuoSourceId, $strCover, 'xs');
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
$arrCover = [
'code' => 'BI_QU_XS_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strFenleiIId = 1;
switch ($strFenlei) {
case '玄幻小说':
$strName = "玄幻";
$strFenleiIId = 1;
break;
case '修真小说':
$strName = "修真";
$strFenleiIId = 2;
break;
case '都市小说':
$strName = "都市";
$strFenleiIId = 3;
break;
case '历史小说':
$strName = "历史";
$strFenleiIId = 4;
break;
case '网游小说':
$strName = "网游";
$strFenleiIId = 5;
break;
case '科幻小说':
$strName = "科幻";
$strFenleiIId = 6;
break;
case '女频小说':
$strName = "女频";
$strFenleiIId = 7;
break;
case '其它小说':
$strName = "其它";
$strFenleiIId = 8;
break;
default:
$strName = "其它";
$strFenleiIId = 8;
break;
}
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe, //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $strFenleiIId,
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceId . '1',
'xsxq_source_code' => 'BIQU_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
$arrZhangjie = [];
$intChapterIndex = 0; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryList->find('.listmain a')->count() > 0) {
$QueryList->find('.listmain a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// 从索引6开始
if ($intChapterIndex >= 12) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
}
$intChapterIndex++;
});
// 输出最终结果
// var_dump($arrZhangjie);
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
//unset($QueryList);
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $XiaoShuoXiangQingModel->xsxq_id)
->max('xszj_pai_xu'); // 获取最大值
var_dump('获取小说章节最大值-' . $intMaxXiaoShuoZhangJiePaixu);
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
// if ($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum) {
// var_dump("小说章节已经入库,不再推送任务");
// continue; // 如果任务已存在,直接跳过 break
// }
$strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
$strZhangJieSourceId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = 'gdbzkz_XIAOSHUO_ZHANGJIE_' . $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieSourceId . '_1';
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJieNum += 1,
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $XiaoShuoXiangQingModel->xsxq_id,
'xsfl_id' => $XiaoShuoXiangQingModel->xsfl_id,
'intZhangJieSort' => 1,
]
];
$TaskCore->set($arrTask);
}
var_dump("章节任务投递成功");
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
$TaskCore = $this->TaskCore;
$strSiteUrl = 'http://www.gdbzkz.info';
var_dump('getNovelReader------------------------------------------------------------------------------------');
$Client = $this->Client;
$intZhangJieSort = $arrData['intZhangJieSort'];
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoId = $arrData['xsxq_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
$strZhangJieName = $arrData['xszj_name'];
$XiaoShuoZhangJieModel = XiaoShuoZhangJieModel::where('xszj_source_code', $strXszjSourceCode)->find();
if ($XiaoShuoZhangJieModel) {
// var_dump($XiaoShuoZhangJieModel->xszj_source_code);
// var_dump('章节已经存在 paixu: ' . $intZhangJiePaiXu);
// var_dump('章节已经存在strXszjSourceCode: ' . $strXszjSourceCode);
// var_dump('章节已经存在strZhangJieUrl: ' . $strZhangJieUrl);
return true;
}
var_dump($strZhangJieUrl);
var_dump('章节排序:' . $intZhangJiePaiXu);
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$ZhangJieQueryList = QueryList::html($strResult);
$strNeiRong = '';
// 获取原始 HTML
$strNeiRong = $ZhangJieQueryList->find('#content')->html();
// 解码 HTML 实体
$strNeiRong = html_entity_decode($strNeiRong, ENT_QUOTES, 'UTF-8');
// 替换不间断空格 (\xc2\xa0) 和 &nbsp; 为普通空格
$strNeiRong = preg_replace('/\xc2\xa0/', ' ', $strNeiRong); // 替换 UTF-8 不间断空格
$strNeiRong = preg_replace('/&nbsp;/', ' ', $strNeiRong); // 替换 &nbsp;
// 清理多余空格和换行符
$strNeiRong = preg_replace('/\s+/', ' ', $strNeiRong);
// 1. 找到所有的 <br> 位置
$br_positions = [];
$offset = 0;
while (($pos = strpos($strNeiRong, "<br", $offset)) !== false) {
$br_positions[] = $pos;
$offset = $pos + 1;
}
// 2. 找到倒数第三个 <br> 的位置
if (count($br_positions) >= 3) {
$cut_position = $br_positions[count($br_positions) - 3]; // 倒数第三个 <br> 的索引
$strNeiRong = substr($strNeiRong, 0, $cut_position); // 截取前面部分,删除后面的内容
}
$arrNeiRong = explode('<br> <br>', $strNeiRong);
$arrEnCode = [];
foreach ($arrNeiRong as $intNeiRongNum => $strNeiRongOne) {
$strEnCode = Base64Helper::encode('<p>' . $strNeiRongOne . '</p>');
$arrEnCode[] = $strEnCode;
}
$strNeiRong = implode(';;;', $arrEnCode);
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel") . '/novel/630zwxs/' . $intFenleiId . '/' . $intXiaoShuoId . '/' . $intZhangJiePaiXu . '/' . $intZhangJieSort . '.txt';
//$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']);
} else {
var_dump("Error: " . $result['message']);
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoId,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
'xszj_sort' => $intZhangJieSort,
];
var_dump($arrXiaoShuoZhangJie);
if ($strZhangJieName) {
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
}
unset($ZhangJieQueryList);
// // 延时 3 秒
//sleep(3);
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJiePaiXu,
'xszj_name' => $strZhangJieName,
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intFenleiId,
'intZhangJieSort' => $intZhangJieSort,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
}

View File

@@ -1,441 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\novelone;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use QL\QueryList;
use app\common\Base64Helper;
/**
* @ 抓取 bqvvxg8.cc 站点相关小说
*/
class NovelWenXueGuanCol extends PullDataColBase
{
public function pullXiaoShuo()
{
$TaskCore = $this->TaskCore;
// https://www.bqvvxg8.cc/wenzhang/86/86114/
$arrNovel = [
['xs_source_id' => 'wenxueguan86114', 'xs_url' => 'https://www.bqvvxg8.cc/wenzhang/86/86114/'],
['xs_source_id' => 'wenxueguan90205', 'xs_url' => 'https://www.bqvvxg8.cc/wenzhang/90/90205/'],
];
foreach ($arrNovel as $Novel) {
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'xs_url' => $Novel['xs_url'],
'xs_source_id' => $Novel['xs_source_id'],
'xs_source_seo_id' => 1,
]
];
$TaskCore->set($arrTask);
var_dump($arrTask);
}
}
public function getNovelInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = 'https://www.bqvvxg8.cc';
$intXiaoShuoSourceId = $arrData['xs_source_id'];
$intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id'];
$strUrl = $arrData['xs_url'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// var_dump($QueryList);
// 提取所有 <meta> 标签的属性
$result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
return [
'property' => $item->attr('property'),
'content' => $item->attr('content'),
];
});
// 打印结果
// print_r($result->all());
$strZuoZhe = '';
$strMingZi = '';
$strLastDate = '';
$strJieShao = '';
$strCover = '';
$strFenlei = '';
$strZiShu = 0;
$strZhuangTai = '';
foreach ($result as $item) {
switch ($item['property']) {
case 'og:title':
$strMingZi = $item['content'];
break;
case 'og:description':
$strJieShao = $item['content'];
break;
case 'og:image':
$strCover = $item['content'];
break;
case 'og:novel:category':
$strFenlei = $item['content'];
break;
case 'og:novel:author':
$strZuoZhe = $item['content'];
break;
case 'og:novel:status':
$strZhuangTai = $item['content'] . '中';
break;
case 'og:novel:update_time':
$strLastDate = $item['content'];
break;
}
}
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadImage($intXiaoShuoSourceId, $strCover, 'xs');
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
$arrCover = [
'code' => 'BI_QU_XS_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$strFenleiIId = 1;
switch ($strFenlei) {
case '玄幻小说':
$strName = "玄幻";
$strFenleiIId = 1;
break;
case '修真小说':
$strName = "修真";
$strFenleiIId = 2;
break;
case '言情小说':
$strName = "都市";
$strFenleiIId = 3;
break;
case '历史小说':
$strName = "历史";
$strFenleiIId = 4;
break;
case '网游小说':
$strName = "网游";
$strFenleiIId = 5;
break;
case '科幻小说':
$strName = "科幻";
$strFenleiIId = 6;
break;
case '女频小说':
$strName = "女频";
$strFenleiIId = 7;
break;
case '其它小说':
$strName = "其它";
$strFenleiIId = 8;
break;
default:
$strName = "其它";
$strFenleiIId = 8;
break;
}
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe, //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $strFenleiIId,
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceId . '1',
'xsxq_source_code' => 'WENXUEGUANG_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
$arrZhangjie = [];
$intChapterIndex = 0; // 定义一个计数器变量
// 检查是否找到元素
if ($QueryList->find('.listmain a')->count() > 0) {
$QueryList->find('.listmain a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// 从索引6开始
if ($intChapterIndex >= 12) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
}
$intChapterIndex++;
});
// 输出最终结果
var_dump($arrZhangjie);
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
//unset($QueryList);
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $XiaoShuoXiangQingModel->xsxq_id)
->max('xszj_pai_xu'); // 获取最大值
var_dump('获取小说章节最大值-' . $intMaxXiaoShuoZhangJiePaixu);
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
var_dump($intZhangJieNum);
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
// if ($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum) {
// var_dump("小说章节已经入库,不再推送任务");
// continue; // 如果任务已存在,直接跳过 break
// }
$strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
$strZhangJieSourceId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = 'gdbzkz_XIAOSHUO_ZHANGJIE_' . $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieSourceId . '_1';
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJieNum += 1,
'xszj_name' => $arrZhangjieOne['mingzi'],
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $XiaoShuoXiangQingModel->xsxq_id,
'xsfl_id' => $XiaoShuoXiangQingModel->xsfl_id,
'intZhangJieSort' => 1,
]
];
$TaskCore->set($arrTask);
}
var_dump("章节任务投递成功");
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
$TaskCore = $this->TaskCore;
$strSiteUrl = 'https://www.bqvvxg8.cc';
var_dump('getNovelReader------------------------------------------------------------------------------------');
$Client = $this->Client;
$intZhangJieSort = $arrData['intZhangJieSort'];
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoId = $arrData['xsxq_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
$strZhangJieName = $arrData['xszj_name'];
$XiaoShuoZhangJieModel = XiaoShuoZhangJieModel::where('xszj_source_code', $strXszjSourceCode)->find();
if ($XiaoShuoZhangJieModel) {
// var_dump($XiaoShuoZhangJieModel->xszj_source_code);
// var_dump('章节已经存在 paixu: ' . $intZhangJiePaiXu);
// var_dump('章节已经存在strXszjSourceCode: ' . $strXszjSourceCode);
// var_dump('章节已经存在strZhangJieUrl: ' . $strZhangJieUrl);
return true;
}
var_dump($strZhangJieUrl);
var_dump('章节排序:' . $intZhangJiePaiXu);
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
'Accept-Charset' => 'GBK, UTF-8, *;q=0.8',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
// 先尝试自动检测编码
$strEncoding = mb_detect_encoding($strResult, ['GBK', 'GB2312', 'BIG5', 'UTF-8'], true);
// 如果不是 UTF-8转换为 UTF-8
if ($strEncoding && $strEncoding !== 'UTF-8') {
$strResult = mb_convert_encoding($strResult, 'UTF-8', $strEncoding);
} else {
// 备用方案,强制转换
$strResult = @iconv('GBK', 'UTF-8//IGNORE', $strResult);
}
// **去掉可能影响解析的 meta 标签**
$strResult = preg_replace('/<meta[^>]+charset=[^>]+>/i', '', $strResult);
// **第一步:使用 QueryList**
$ZhangJieQueryList = QueryList::html($strResult);
$strNeiRong = '';
// 获取原始 HTML
$strNeiRong = $ZhangJieQueryList->find('#content')->html();
// 解码 HTML 实体
$strNeiRong = html_entity_decode($strNeiRong, ENT_QUOTES, 'UTF-8');
// 替换不间断空格 (\xc2\xa0) 和 &nbsp; 为普通空格
$strNeiRong = preg_replace('/\xc2\xa0/', ' ', $strNeiRong); // 替换 UTF-8 不间断空格
$strNeiRong = preg_replace('/&nbsp;/', ' ', $strNeiRong); // 替换 &nbsp;
// 清理多余空格和换行符
$strNeiRong = preg_replace('/\s+/', ' ', $strNeiRong);
// 1. 找到所有的 <br> 位置
$br_positions = [];
$offset = 0;
while (($pos = strpos($strNeiRong, "<br", $offset)) !== false) {
$br_positions[] = $pos;
$offset = $pos + 1;
}
// 2. 找到倒数第三个 <br> 的位置
if (count($br_positions) >= 3) {
$cut_position = $br_positions[count($br_positions) - 3]; // 倒数第三个 <br> 的索引
$strNeiRong = substr($strNeiRong, 0, $cut_position); // 截取前面部分,删除后面的内容
}
$arrNeiRong = explode('<script>app2();</script><br>', $strNeiRong);
$strNeiRong = $arrNeiRong[1];
$arrNeiRong = explode('<br><br>', $strNeiRong);
$arrEnCode = [];
foreach ($arrNeiRong as $intNeiRongNum => $strNeiRongOne) {
$strEnCode = Base64Helper::encode('<p>' . $strNeiRongOne . '</p>');
$arrEnCode[] = $strEnCode;
}
$strNeiRong = implode(';;;', $arrEnCode);
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel") . '/novel/630zwxs/' . $intFenleiId . '/' . $intXiaoShuoId . '/' . $intZhangJiePaiXu . '/' . $intZhangJieSort . '.txt';
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']);
} else {
var_dump("Error: " . $result['message']);
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoId,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
'xszj_sort' => $intZhangJieSort,
];
if ($strZhangJieName) {
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
}
unset($ZhangJieQueryList);
//sleep(3);
} catch (\Throwable $T) {
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieSourceId,
'xszj_paixu' => $intZhangJiePaiXu,
'xszj_name' => $strZhangJieName,
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_id' => $intXiaoShuoId,
'xsfl_id' => $intFenleiId,
'intZhangJieSort' => $intZhangJieSort,
]
];
$TaskCore->set($arrTask);
throw $T;
}
}
}

View File

@@ -1,137 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\model\VideoInfoModel;
use app\model\SystemConfigModel;
use app\model\VideoClassModel;
class GenerateSiteMapCol extends PullDataColBase
{
public function generate()
{
$strSiteDomain = SystemConfigModel::getValByCode('YONG_JIU_DOMAIN');
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有视频总数
$totalVideoCount = VideoInfoModel::count();
// 获取分类信息
$categories = VideoClassModel::getDataByCache();
// 生成视频详情的 Sitemap
$videoSitemapFiles = $this->generateVideoSitemaps($chunkSize, $totalVideoCount, $strSiteDomain);
// 生成分类的 Sitemap
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($videoSitemapFiles, $categorySitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
private function generateVideoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$videos = VideoInfoModel::field('v_pinyin')
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($videos, $strSiteDomain);
$filePath = public_path() . "sitemap_video_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateCategorySitemaps(array $categories, string $strSiteDomain): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['vc_id'];
$vcNicheng = $category['vc_nicheng'];
$vcName = $category['vc_name'];
$videoCount = VideoInfoModel::where('vc_id', $vcId)->count();
$totalPages = ceil($videoCount / 30);
$categoryUrls = [];
$categoryUrls[] = [
'url' => "/vodtype/{$vcNicheng}.html",
'title' => "{$vcName} - 首页",
'is_home' => true,
];
for ($page = 2; $page <= $totalPages; $page++) {
$categoryUrls[] = [
'url' => "/vodshow/{$vcNicheng}--------{$page}---.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, true);
$filePath = public_path() . "sitemap_category_{$vcNicheng}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function buildSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/voddetail/' . htmlspecialchars($item['v_pinyin'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -1,188 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\model\SystemConfigModel;
use app\model\SiteModel;
use app\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovel extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain);
// 生成章节的 Sitemap
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain);
// 生成分类的 Sitemap
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $categorySitemapFiles,$novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id','xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id','xsxq_source_id','xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateCategorySitemaps(array $categories, string $strSiteDomain): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($type = 0; $type <= 3; $type++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fenlei/1-0-1.html
'url' => "/fenlei/{$vcId}-{$type}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function buildZjSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// zj/18648-206.html
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/zj/' . htmlspecialchars($item['xsxq_id'].'-'.$item['xszj_id']. '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/20052-16107-161071.html
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/xq/' . htmlspecialchars($item['xsxq_id'].'-'.$item['xsxq_source_id'].'-'.$item['xsxq_source_seo_id']. '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -1,242 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\model\XiaoShuoXiangQingModel;
use app\model\NovelInfoSeoModel;
use app\model\XiaoShuoZhangJieModel;
use app\model\SiteModel;
use app\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovelSk extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
// $strSiteDomain = SiteModel::getValBySiteIdByValCode('site_domain');
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelSeoCount = NovelInfoSeoModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap 小说详情
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain, $strXqPath);
// 生成详情的 Sitemap 小说seo
$novelSeoSitemapFiles = $this->generateNovelSeoSitemaps($chunkSize, $totalNovelSeoCount, $strSiteDomain, $strSeoPath);
// 生成章节的 Sitemap 小说章节
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain, $strXqPath);
// 生成分类的 Sitemap 小说分类
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain, $strFenleiPath, $strXqPath);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $novelSeoSitemapFiles, $categorySitemapFiles, $novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
# 生成小说章节 xml文件
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id', 'xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id', 'xsxq_source_id', 'xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSeoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strSeoPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = NovelInfoSeoModel::field(['xsxq_id', 'nis_id']) //show/nis_id
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildXiaoShuoSeoSitemap($Novels, $strSiteDomain, $strSeoPath);
$filePath = public_path() . "sitemap_novel_seo_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
// 生成分类链接
private function generateCategorySitemaps(array $categories, string $strSiteDomain, string $strFenleiPath, string $strXqPath): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($status = 0; $status <= 2; $status++) {
for ($sort = 0; $sort <= 4; $sort++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fl/:intCId-:intSort-[:intPage]
'url' => "/{$strFenleiPath}/{$vcId}-{$sort}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, $strXqPath, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
//生成章节链接
private function buildZjSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId/:intZhangJiePaiXu-[:strSort]
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '-' . $item['xszj_pai_xu']. '-' . $item['xszj_sort'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 详情链接
private function buildSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成详情 seo 链接
private function buildXiaoShuoSeoSitemap(array $items, string $strSiteDomain, string $strSeoPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /show/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strSeoPath . '/' . htmlspecialchars($item['nis_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 xml 文件
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -1,242 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\model\XiaoShuoXiangQingModel;
use app\model\NovelInfoSeoModel;
use app\model\XiaoShuoZhangJieModel;
use app\model\SiteModel;
use app\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovelZw extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
// $strSiteDomain = SiteModel::getValBySiteIdByValCode('site_domain');
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelSeoCount = NovelInfoSeoModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap 小说详情
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain, $strXqPath);
// 生成详情的 Sitemap 小说seo
$novelSeoSitemapFiles = $this->generateNovelSeoSitemaps($chunkSize, $totalNovelSeoCount, $strSiteDomain, $strSeoPath);
// 生成章节的 Sitemap 小说章节
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain, $strXqPath);
// 生成分类的 Sitemap 小说分类
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain, $strFenleiPath, $strXqPath);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $novelSeoSitemapFiles, $categorySitemapFiles, $novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
# 生成小说章节 xml文件
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id', 'xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id', 'xsxq_source_id', 'xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSeoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strSeoPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = NovelInfoSeoModel::field(['xsxq_id', 'nis_id']) //show/nis_id
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildXiaoShuoSeoSitemap($Novels, $strSiteDomain, $strSeoPath);
$filePath = public_path() . "sitemap_novel_seo_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
// 生成分类链接
private function generateCategorySitemaps(array $categories, string $strSiteDomain, string $strFenleiPath, string $strXqPath): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($status = 0; $status <= 2; $status++) {
for ($sort = 0; $sort <= 4; $sort++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fl/:intCId-:intSort-[:intPage]
'url' => "/{$strFenleiPath}/{$vcId}-{$sort}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, $strXqPath, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
//生成章节链接
private function buildZjSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId/:intZhangJiePaiXu-[:strSort]
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '-' . $item['xszj_pai_xu']. '-' . $item['xszj_sort'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 详情链接
private function buildSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成详情 seo 链接
private function buildXiaoShuoSeoSitemap(array $items, string $strSiteDomain, string $strSeoPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /show/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strSeoPath . '/' . htmlspecialchars($item['nis_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 xml 文件
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -1,538 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\tianlai;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class TianLaiXiaoShuoCol extends PullDataColBase
{
public function pullXiaoShuo()
{
$TaskCore = $this->TaskCore;
$strUrl = $this->getTianLaiDomain();
var_dump($strUrl);
$Client = $this->Client;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
// $proxy = '127.0.0.1:8080'; // 代理地址
// $response = fetchContentWithCurl($strUrl, [], 10, $proxy);
$strResult = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$strResult->getBody();
var_dump($strResult);
// exit;
// $strResult = $response['data'];
$QueryList = QueryList::html($strResult);
$QueryList->find('.nav a')->map(function ($FenLeiQueryList) use ($strUrl, $TaskCore) {
$strName = trim($FenLeiQueryList->text());
switch ($strName) {
case '都市言情':
$strName = "都市言情";
break;
case '历史军事':
$strName = "历史军事";
break;
case '玄幻奇幻':
$strName = "玄幻奇幻";
break;
case '武侠修真':
$strName = "武侠修真";
break;
case '女生纯爱':
$strName = "女频言情";
break;
case '科幻网游':
$strName = "科幻网游";
break;
case '悬疑灵异':
$strName = "悬疑灵异";
break;
default:
$strName = "其它";
break;
}
$strFenLeiUrl = $strUrl . $FenLeiQueryList->attr('href');
// $intFenLeiId = extractFilename($strFenLeiUrl."index.html");
$intFenLeiId = extractNumberFromUrl($strFenLeiUrl);
if($intFenLeiId !== null){
$arrClass = [
'xsfl_source_id' => $intFenLeiId,
'xsfl_source_code' => 'TIANLAI_FEN_LEI_ID_' . $intFenLeiId,
'xsfl_name' => $strName,
];
var_dump($arrClass);
$XiaoShuoFenLeiModel = XiaoShuoFenLeiModel::addXiaoShuoFenLei($arrClass);
$arrTask = [
'callback' => [self::class, 'getNovelPage'],
'data' => [
'url' => $strFenLeiUrl,
'xsfl_source_id' => $intFenLeiId,
'xsfl_name' => $strName,
'xsfl_id' => $XiaoShuoFenLeiModel->xsfl_id,
'xsfl_page' => 1,
'xsfl_max_page' => 3000,
]
];
$TaskCore->set($arrTask);
}
});
} catch (\Throwable $T) {
//var_dump($T);
throw $T;
}
}
public function getNovelPage($arrData)
{
var_dump('getNovelPage');
var_dump($arrData);
$strBasePage = $arrData['url'];
$Client = $this->Client;
$TaskCore = $this->TaskCore;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strBasePage);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getTianLaiDomain();
$intPage = $arrData['xsfl_page'];
$intMaxPage = $arrData['xsfl_max_page'];
$strUrl = $strBasePage;
var_dump($strUrl);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$strResult = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent
],
'cookies' => $CookieJar,
#'proxy' => $proxy,
'timeout' => 10,
]);
$strResult = (string)$strResult->getBody();
$QueryList = QueryList::html($strResult);
$intMaxPage = $QueryList->find('#newscontent h2 span')->eq(1)->text();
$intMaxPage = ceil($intMaxPage / 100);
var_dump($intMaxPage);
$intMaxPage = 2;
var_dump('$strUrl');
// 如果是首页 则根据最大页面吧所有分页 追加到任务
if($intPage == 1){
for ($intCurrentPage = 2; $intCurrentPage <= $intMaxPage; $intCurrentPage++) {
$strNewsFenleiUrl = replaceLastPageNumber($strBasePage, $intCurrentPage);
var_dump($strNewsFenleiUrl);
$arrTask = [
'callback' => [self::class, 'getNovelPage'],
'data' => [
'url' => $strNewsFenleiUrl,
'xsfl_source_id' => $arrData['xsfl_source_id'],
'xsfl_name' => $arrData['xsfl_name'],
'xsfl_id' => $arrData['xsfl_id'],
'xsfl_page' => $intCurrentPage,
'xsfl_max_page' => $intMaxPage,
]
];
$TaskCore->set($arrTask);
}
}
var_dump('提取小说');
$XiaoShuoListQueryList = $QueryList->find('#newscontent li');
if (!$XiaoShuoListQueryList || $XiaoShuoListQueryList->count() <= 0) {
var_dump('这个分类已经市最后一页');
return true;
}
var_dump($XiaoShuoListQueryList->count());
var_dump('提取小说2');
// var_dump($XiaoShuoListQueryList);
$XiaoShuoListQueryList->map(function ($XiaoShuoQueryList) use ($strSiteUrl, $arrData, $TaskCore, $strUrl) {
// 提取小说链接
// var_dump($XiaoShuoQueryList->html());exit;
var_dump('提取小说链接');
$A = $XiaoShuoQueryList->find('a')->eq(0);
$strXiaoShuoUrl = $A->attr('href');
$strXiaoShuoUrl = strpos($strXiaoShuoUrl, 'https:') === 0 ? $strXiaoShuoUrl : 'https:' . $strXiaoShuoUrl;
var_dump('$A');
var_dump($A);
var_dump($strXiaoShuoUrl);
exit;
// var_dump($A);
// 提取作者信息
$strZuoZhe = trim($XiaoShuoQueryList->find('.s4')->eq(0)->text());
// 提取小说 ID
$arrXiaoShuoId = extractNumbersFromUrl($strXiaoShuoUrl);
if (!isset($arrXiaoShuoId['first'], $arrXiaoShuoId['second'])) {
return; // 如果 ID 提取失败,直接跳过
}
// 准备任务数据
$arrXiaoShuo = array_merge($arrData, [
'xiaoshuo_url' => $strXiaoShuoUrl,
'xiaoshuo_id' => $arrXiaoShuoId['first'],
'xiaoshuo_seo_id' => $arrXiaoShuoId['second'],
'xiaoshuo_zuozhe' => $strZuoZhe,
'url' => $strUrl
]);
var_dump($arrXiaoShuo);
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => $arrXiaoShuo,
];
// 将任务加入队列
$TaskCore->set($arrTask);
var_dump("将任务加入队列getNovelInfo-{$strXiaoShuoUrl}");
});
var_dump('提取小说end');
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelInfo($arrData)
{
var_dump('getNovelInfo');
var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getTianLaiDomain();
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $arrData['xiaoshuo_url'], [
'headers' => [
'User-Agent' => $userAgent
],
'cookies' => $CookieJar,
#'proxy' => $proxy,
'timeout' => 10,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$QueryList = QueryList::html($strResult);
$strMingZi = $QueryList->find('#info h1')->eq(0)->text();
$strZhuangTai = "状态:连载中";
$strZiShu = 0;
$strZhuangTai = getStringAfterWord($strZhuangTai, '状态:');
// 提取作者信息
$strZuoZhe = trim($QueryList->find('p a')->eq(0)->text());
// $strLastDate = $QueryList->find('meta[property="og:novel:update_time"]')->attr('content');
$strLastDate = $QueryList->find('#info p')->eq(2)->text();
$strLastDate = getStringAfterWord($strLastDate, '最后更新:');
$strLastDate = trim((string)$strLastDate);
if (!isValidDateTime($strLastDate)) {
$strLastDate = date('Y-m-d H:i:s');
}
$arrTag = [];
// $QueryList->find('.tg span')->map(function ($TagQuery) use (&$arrTag) {
// $arrTag[] = trim($TagQuery->text());
// });
$strJieShao = $QueryList->find('#intro')->eq(0)->text();
$strJieShao = removeScriptTags('/<script>.*?<\/script>/is',$strJieShao) ;
$strJieShao = removeScriptTags('/myJs\.bookJs\(\);/',$strJieShao) ;
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
// if (strpos($strCover, 'http') === false) {
// $strCover = $strSiteUrl . $strCover;
// }
$strCoverUri = $strCover;
// try {
// $strCoverUri = "";
// $strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
// } catch (\Throwable $t) {
// $strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
// echo $strErr;
// }
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_ming_zi' => $strMingZi,
'xsxq_zuozhe' => $strZuoZhe , //$arrData['xiaoshuo_zuozhe'],
'xsfl_id' => $arrData['xsfl_id'],
'xsxq_zhuang_tai' => $strZhuangTai,
'xsxq_zi_shu' => $strZiShu,
'xsxq_jie_shao' => $strJieShao,
'xsxq_feng_mian' => json_encode($arrCover),
'xsxq_geng_xin_shi_jian' => $strLastDate,
'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
'xsxq_source_id' => $intXiaoShuoSourceId,
'xsxq_source_seo_id' => $intXiaoShuoSourceSeoId,
'xsxq_source_code' => 'AILISI_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
];
// print_r($arrXiaoShuoInfo);
var_dump($arrXiaoShuoInfo['xsxq_source_code']);
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
/*
if ($redis->exists($redisKey)) {
var_dump('小说任务已存在,直接跳过');
return true; // 如果任务已存在,直接跳过
}
// 在 Redis 中标记任务为已存在
$redis->set($redisKey, 1);
$arrZhangjie = [];
$QueryList->find('#list a')->map(function ($ZhangJie) use (&$arrZhangjie) {
$arrZhangjie[] = [
'mingzi' => $ZhangJie->text(),
'url' => $ZhangJie->attr('href'),
];
});
unset($QueryList);
// 获取最大章节索引
$intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuoSourceId)
->max('xszj_pai_xu'); // 获取最大值
// 如果没有结果max 返回 null可以设置默认值
$intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
// 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
var_dump("小说章节已经入库,不再推送任务");
continue;// 如果任务已存在,直接跳过 break
}
$strZhangJieUrl = "https:" . $arrZhangjieOne['url'];
$strZhangJieId = extractFilename($strZhangJieUrl);
# 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
$strXszjSourceCode = 'AILISI_XIAOSHUO_ZHANGJIE_'. $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieId;
$arrTask = [
'callback' => [self::class, 'getNovelReader'],
'data' => [
'xszj_source_id' => $strZhangJieId,
'xszj_paixu' => $intZhangJieNum,
'xszj_url' => $strZhangJieUrl,
'xszj_source_code' => $strXszjSourceCode,
'xsxq_source_id' => $XiaoShuoXiangQingModel->xsxq_source_id,
'xsfl_id' => $arrData['xsfl_id'],
]
];
$TaskCore->set($arrTask);
//var_dump("章节任务投递成功".$strXszjSourceCode);
}
// 任务成功后删除 Redis 标记
$redis->del($redisKey);
*/
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelFengMian($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$TaskCore = $this->TaskCore;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getTianLaiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
public function getNovelReader($arrData)
{
//var_dump('getNovelReader');
//var_dump($arrData);
$Client = $this->Client;
$strXszjSourceCode = $arrData['xszj_source_code'];
$strZhangJieUrl = $arrData['xszj_url'];
$intZhangJiePaiXu = $arrData['xszj_paixu'];
$intFenleiId = $arrData['xsfl_id'];
$intXiaoShuoSourceID = $arrData['xsxq_source_id'];
$strZhangJieSourceId = $arrData['xszj_source_id'];
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strZhangJieUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
return true;
}
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strZhangJieUrl, [
'headers' => [
'User-Agent' => $userAgent
],
'cookies' => $CookieJar,
#'proxy' => $proxy,
'timeout' => 10,
]);
$strResult = (string)$Response->getBody();
unset($Response);
$ZhangJieQueryList = QueryList::html($strResult);
$strZhangJieName = $ZhangJieQueryList->find('h1')->text();
$strNeiRong = $ZhangJieQueryList->find('#content')->eq(0)->text();
# '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
$strNeiRongTxtPath = config("filesystem.novel").'/novel/123yqw/'.$intFenleiId.'/'.$intXiaoShuoSourceID.'/'.$strZhangJieSourceId.'.txt';
//$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// 调用函数
$result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// 输出状态
if ($result['status']) {
var_dump("Success: " . $result['message']) ;
} else {
var_dump("Error: " . $result['message']) ;
}
$arrXiaoShuoZhangJie = [
'xsxq_id' => $intXiaoShuoSourceID,
'xszj_pai_xu' => $intZhangJiePaiXu,
'xszj_ming_zi' => $strZhangJieName,
'xszj_nei_rong' => $strNeiRongTxtPath,
'xszj_source_id' => $strZhangJieSourceId,
'xszj_source_code' => $strXszjSourceCode,
];
XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
unset($ZhangJieQueryList);
} catch (\Throwable $T) {
throw $T;
}
}
}

View File

@@ -1,90 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\visitlogs;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
use app\model\VisitLogsModel;
use app\model\ContentStatsModel;
/**
* @mixin think\Model
*/
class ContentStatsCol extends PullDataColBase
{
public function run()
{
var_dump('ContentStatsCol');
try {
// 定义时间范围统计的周期类型和 SQL 表达式
$arrPeriods = [
'day' => "DATE(vil_timestamp)", // 按日统计
'week' => "YEARWEEK(vil_timestamp)", // 按周统计
'month' => "DATE_FORMAT(vil_timestamp, '%Y-%m')", // 按月统计
'quarter' => "CONCAT(YEAR(vil_timestamp), '-', QUARTER(vil_timestamp))", // 按季度统计
'year' => "YEAR(vil_timestamp)" // 按年统计
];
foreach ($arrPeriods as $periodName => $groupExpression) {
var_dump($groupExpression);
$results = VisitLogsModel::where('vil_is_spider', 0) // 排除爬虫访问
->field([
'vil_content_type',
'vil_content_id',
"$groupExpression" => 'stat_date', // 根据周期分组
'COUNT(*)' => 'pv', // PV
'COUNT(DISTINCT vil_ip)' => 'uv' // UV
])
->group('vil_content_type, vil_content_id, stat_date')
->select()->toArray();
// var_dump($results);
foreach ($results as $result) {
$ContentStatsModel = [
'cs_content_type' => $result['vil_content_type'],
'cs_content_id' => $result['vil_content_id'],
'cs_stat_date' => $result['stat_date'],
'cs_stat_period' => $periodName, // 周期类型day, week, month, quarter, year
'cs_pv' => $result['pv'],
'cs_uv' => $result['uv'],
'cs_md5' => md5($result['vil_content_type'].$result['vil_content_id'].$result['stat_date'].$periodName),
'updated_at' => date('Y-m-d H:i:s'),
];
var_dump($ContentStatsModel);
ContentStatsModel::add($ContentStatsModel);
// var_dump($r);
// 插入或更新到统计表
// ContentStatsModel::insertOrUpdate([
// 'cs_content_type' => $result['vil_content_type'],
// 'cs_content_id' => $result['vil_content_id'],
// 'cs_stat_date' => $result['stat_date'],
// 'cs_stat_period' => $periodName, // 周期类型day, week, month, quarter, year
// 'cs_pv' => $result['pv'],
// 'cs_uv' => $result['uv'],
// 'updated_at' => date('Y-m-d H:i:s'),
// ], [
// 'cs_content_type' => $result['vil_content_type'],
// 'cs_content_id' => $result['vil_content_id'],
// 'cs_stat_date' => $result['stat_date'],
// 'cs_stat_period' => $periodName,
// ]);
}
}
} catch (\Exception $e) {
// 记录异常日志
//\think\facade\Log::error('ContentStatsTask error: ' . $e->getMessage());
}
}
}

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\visitlogs;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
use app\model\VisitLogsModel;
/**
* @mixin think\Model
*/
class VisitLogsCol extends PullDataColBase
{
public function add($arrData)
{
try {
// 'vil_ip', 'vil_url', 'vil_content_id', 'vil_content_type', 'vil_method'
if (empty($arrData['vil_ip']) || empty($arrData['vil_url']) || empty($arrData['vil_content_id']) || empty($arrData['vil_content_type']) || empty($arrData['vil_method'])) {
var_dump("信息不全!");
}else{
$strLocation = '';
// if(!empty($arrData['vil_ip'])){
// $strLocation = getLocationByIp($arrData['vil_ip']);
// }
$arrData['vil_location'] = $strLocation;
VisitLogsModel::add($arrData);
}
} catch (\Throwable $T) {
//var_dump($T);
throw $T;
}
}
}

View File

@@ -1,375 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\collection\yzzy;
use app\model\VideoYuyanModel;
use app\model\VideoPlayurlModel;
use app\model\VideoLeixinModel;
use app\model\VideoDiquModel;
use app\model\VideoYearsModel;
use app\model\VideoJuqingModel;
use app\model\XiaoShuoFenLeiModel;
use app\model\XiaoShuoXiangQingModel;
use app\model\VideoInfoModel;
use app\model\XiaoShuoZhangJieModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model 优质资源
*/
class YouZhiYingShiCol extends PullDataColBase
{
public function pullYouZhiYingshi()
{
// https://1080zyk1.com/?m=vod-type-id-1-pg-1.html
// https://1080zyk1.com/?m=vod-type-id-2-pg-2.html
// https://1080zyk1.com/?m=vod-type-id-3-pg-2.html
// https://1080zyk1.com/?m=vod-type-id-4-pg-2.html
// https://1080zyk1.com/?m=vod-type-id-83-pg-2.html
// https://1080zyk1.com/?m=vod-type-id-94-pg-2.html
$strSiteUrl = $this->YouZhiZiYuanDomain();
// 配置分类任务参数
$categories = [
['id' => 1, 'video_class_id' => 1, 'name' => '电影'],
['id' => 83, 'video_class_id' => 5, 'name' => '短剧'],
['id' => 2, 'video_class_id' => 2, 'name' => '电视剧'],
['id' => 3, 'video_class_id' => 3, 'name' => '综艺'],
['id' => 4, 'video_class_id' => 4, 'name' => '动漫'],
['id' => 94, 'video_class_id' => 6, 'name' => '体育'],
];
foreach ($categories as $category) {
$intClassId = $category['video_class_id'];
$intCategoryId = $category['id'];
// 先抓第一页
$strUrl = $strSiteUrl . '/?m=vod-type-id-' . $intCategoryId . '-pg-1.html';
var_dump($strUrl);
$maxPage = $this->getMaxPage($strUrl,$intClassId);
// 首次抓取,全部抓取
if (config('task.task_is_first')) {
$this->createTasks($strSiteUrl, $intCategoryId, $intClassId, $maxPage);
}
}
}
/**
* 获取分类的最大页码且抓取第一页
*/
protected function getMaxPage($strUrl, $intClassId)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'en-US,en;q=0.5',
'cookie' => '__sk_Vm8nTqM7LqSCWmR6__=be3bd4f4e0483619e1a434ec1b18a938',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 300,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// 检查是否找到元素
$intVideoListIndex = 0;
if ($QueryList->find('.xing_vb ul')->count() > 1) {
$QueryList->find('.xing_vb ul')->map(function ($Video) use ($intClassId, &$TaskCore,&$intVideoListIndex) {
if($intVideoListIndex >=1){
$strHref = $Video->find('.xing_vb4 a')->attr('href');
$strName = '';
if (!empty($strHref) && strlen($strHref) > 0) {
$arrTask = [
'callback' => [self::class, 'getVideoInfo'],
'data' => [
'class_id' => $intClassId,
'video_href' => $strHref,
'video_name' => $strName,
]
];
// var_dump($arrTask);
$TaskCore->set($arrTask);
echo "视频投递成功 : " . $Video->text() . PHP_EOL;
}
}
$intVideoListIndex ++ ;
});
} else {
echo "No elements found for .xing_vb ul" . PHP_EOL;
}
// 获取分页部分最后一个页码链接
$lastPageHref = $QueryList->find('.pages a')->eq($QueryList->find('.pages a')->count() - 1)->attr('href');
// 提取最大页码
preg_match('/-pg-(\d+)\.html/', $lastPageHref, $matches);
$maxPage = isset($matches[1]) ? (int)$matches[1] : 1; // 默认返回 1
return $maxPage;
}
/**
* 创建任务
*/
protected function createTasks($strSiteUrl, $intCategoryId, $videoClassId, $maxPage)
{
$TaskCore = $this->TaskCore;
for ($i = $maxPage; $i >= 1; $i--) {
echo "当前分类: $intCategoryId, 当前页: $i\n";
$arrTask = [
'callback' => [self::class, 'getVideoPage'],
'data' => [
'video_page_url' => $strSiteUrl . '/?m=vod-type-id-' . $intCategoryId . '-pg-' . $i . '.html',
'video_class_id' => $videoClassId,
]
];
$TaskCore->set($arrTask);
}
}
# 获取分页里面的视频列表
public function getVideoPage($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strUrl = $arrData['video_page_url'];
$intClassId = $arrData['video_class_id'];
$strSiteUrl = $this->YouZhiZiYuanDomain();
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
var_dump($strUrl);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'en-US,en;q=0.5',
'cookie' => '__sk_Vm8nTqM7LqSCWmR6__=be3bd4f4e0483619e1a434ec1b18a938',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 300,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
$intVideoListIndex = 0;
if ($QueryList->find('.xing_vb ul')->count() > 1) {
$QueryList->find('.xing_vb ul')->map(function ($Video) use ($intClassId, &$TaskCore,&$intVideoListIndex) {
if($intVideoListIndex >=1){
$strHref = $Video->find('.xing_vb4 a')->attr('href');
$strName = '';
if (!empty($strHref) && strlen($strHref) > 0) {
$arrTask = [
'callback' => [self::class, 'getVideoInfo'],
'data' => [
'class_id' => $intClassId,
'video_href' => $strHref,
'video_name' => $strName,
]
];
// var_dump($arrTask);
$TaskCore->set($arrTask);
echo "视频投递成功 : " . $strHref . PHP_EOL;
}
}
$intVideoListIndex ++ ;
});
} else {
echo "No elements found for .xing_vb ul" . PHP_EOL;
}
}
public function getVideoInfo($arrData)
{
$TaskCore = $this->TaskCore;
$Client = $this->Client;
$strSiteUrl = $this->YouZhiZiYuanDomain();
$strUrl = $strSiteUrl . $arrData['video_href'];
$intClassId = $arrData['class_id'];
$strVideoName = $arrData['video_name'] ?? '';
var_dump($strUrl);
if (!empty($strUrl) && strlen($strUrl) > 0) {
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($strUrl);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$proxy = getRandomProxies();
$userAgent = getRandomUserAgent();
$Response = $Client->request('GET', $strUrl, [
'headers' => [
'User-Agent' => $userAgent,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language' => 'en-US,en;q=0.5',
],
'cookies' => $CookieJar,
// 'proxy' => $proxy,
'timeout' => 30,
]);
$strResult = (string)$Response->getBody();
$QueryList = QueryList::html($strResult);
// 提取别名
$strPinyinId = 'yzzy'.extractIdFromUrl($strUrl);
$strVideoName = $QueryList->find('.vodh h2')->text();
$strJiaoBiao = $QueryList->find('.vodh span')->text();
$strPinfen = $QueryList->find('.vodh label')->text();
$strLeixin = $QueryList->find('.nvc dd a')->eq(1)->text();
$strCover = $QueryList->find('.vodImg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
$arrCover = [
'code' => 'YOUZHI_SOURCE_COVER',
'uri' => $strCoverUri,
];
// 提取导演
$strDaoyan = $QueryList->find('.vodInfo .vodinfobox ul li')->eq(1)->find('span')->text();
// 提取主演 多个逗号分割
$strZhuyan = $QueryList->find('.vodInfo .vodinfobox li')->eq(2)->find('span')->text();
// 提取类型
$arrLeixinData = $QueryList->find('.vodInfo .vodinfobox li')->eq(3)->find('span')->text();
// 切割后移除空元素
$arrJuqing = preg_split('/\s+/u', trim($arrLeixinData));
array_shift($arrJuqing);
// **在过滤后将“类型”数据入库**
foreach ($arrJuqing as $value) {
if(strlen($value) > 0){
VideoJuqingModel::add(['vc_id' => $intClassId, 'vj_name' => $value]);
}
}
// 提取地区
$strDiqu = $QueryList->find('.vodinfobox li span')->eq(4)->text();
// 提取语言
$strLanguage = $QueryList->find('.vodinfobox li span')->eq(5)->text();
// 提取年份
$strYears = $QueryList->find('.vodinfobox li span')->eq(6)->text();
// 提取更新时间
$strLastDate = $QueryList->find('.vodinfobox li span')->eq(8)->text();
if (strlen($strLeixin) > 0) {
VideoLeixinModel::addVideoLeixin(['vc_id' => $intClassId, 'vl_name' => $strLeixin]);
}
if (strlen($strDiqu) > 0) {
VideoDiquModel::add(['vc_id' => $intClassId, 'vd_name' => $strDiqu]);
}
if (strlen($strYears) > 0) {
VideoYearsModel::add(['vc_id' => $intClassId, 'vy_name' => $strYears]);
}
if (strlen($strLanguage) > 0) {
VideoYuyanModel::add(['vc_id' => $intClassId, 'vla_name' => $strLanguage]);
}
// 提取简介
$strDescription = $QueryList->find('.vodplayinfo')->eq(0)->text();
if(empty($strVideoName)){
var_dump('$strVideoName------');
var_dump($strVideoName);
return true;
}
$arrVideoInfo = [
'v_name' => $strVideoName,
'v_cover' => json_encode($arrCover),
'vc_id' => $intClassId,
'v_pinyin' => $strPinyinId,
'v_leixin' => $strLeixin,
'v_juqing' => implode(',', $arrJuqing),
'v_diqu' => $strDiqu,
'v_years' => $strYears,
'v_language' => $strLanguage,
'v_daoyan' => trim(str_replace('主演:', '', $strZhuyan)),
'v_zhuyan' => trim(str_replace('导演:', '', $strDaoyan)),
'update_time' => $strLastDate,
'v_description' => $strDescription,
'v_pingfen' => $strPinfen,
'v_orurl' => $strUrl,
'v_jiaobiao' => $strJiaoBiao,
'v_md5' => md5($intClassId .$strPinyinId. $strVideoName . getUriByUrl($strUrl)),
];
// var_dump($arrVideoInfo);
// // 检查是否找到元素
if ($QueryList->find('#play_2 ul li')->count() > 0) {
// var_dump("视频入库成功--" . $strVideoName);
$resultVideoInfoModel = VideoInfoModel::addVideoXiangQing($arrVideoInfo);;
if ($resultVideoInfoModel['isNew']) {
var_dump("视频详情数据已新增:", $resultVideoInfoModel['model']->v_id."视频入库成功--" . $strVideoName);
} else {
echo "视频详情数据已存在:", $resultVideoInfoModel['model']->v_id;
}
$VideoInfoModel = $resultVideoInfoModel['model'];
$intVid = $VideoInfoModel->v_id;
$intChapterIndex = 0;
$QueryList->find('#play_2 ul li')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex, &$intVid,&$intClassId) {
//echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
$strM3u8 = $ZhangJie->find('a')->text();
$arrM3u8 = explode('$', $strM3u8);
$strM3u8Url = $arrM3u8[1];
$strM3u8Name = $arrM3u8[0];
$arrM3u8Url = [
'code' => 'YOUZHI_SOURCE_PLAY',
'uri' => $strM3u8Url,
];
$arrVideoPlayurl = [
'v_id' => $intVid,
'vp_sort' => $intChapterIndex,
'vp_name' => $strM3u8Name,
'vp_url' => json_encode($arrM3u8Url),
'vp_md5' => md5($intClassId.$intVid . getUriByUrl($strM3u8Url)),
];
$result = VideoPlayurlModel::add($arrVideoPlayurl);
if ($result['isNew']) {
var_dump("播放地址已新增:", $result['model']->vp_id."播放线路入库成功--" . $strM3u8Url) ;
} else {
echo "播放地址已存在:", $result['model']->vp_id ;
}
$intChapterIndex++;
});
var_dump("--") ;
var_dump("一个视频任务完成------------------------------------------------------------------------------------") ;
} else {
echo "No elements found for .listmain a" . PHP_EOL;
}
} catch (\Throwable $T) {
throw $T;
}
}
// sleep(10);
}
}

View File

@@ -0,0 +1,477 @@
<?php
declare(strict_types=1);
namespace app\task\collection\zw630;
use app\model\XiaoShuoXiangQingModel;
use app\task\collection\PullDataColBase;
use GuzzleHttp\Cookie\CookieJar;
use processor\ImageProcessor;
use think\facade\Cache;
use QL\QueryList;
/**
* @mixin think\Model
*/
class Zw630Col extends PullDataColBase
{
public function pull630ZwNovel()
{
// 全局扫描任务
$QueueManage = $this->QueueManage;
for ($i = 1; $i <= 531208; $i++) {
$arrTask = [
'callback' => [self::class, 'getNovelInfo'],
'data' => [
'n_id' => $i,
]
];
print_r($arrTask);
// $QueueManage->set($arrTask);
}
}
public function getNovelInfo($arrData)
{
//var_dump('getNovelFengMian');
//var_dump($arrData);
$Client = $this->Client;
$QueueManage = $this->QueueManage;
// 获取 Redis 实例
$redis = Cache::store('redis')->handler();
$intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
$intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
$redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
try {
$arrCookie = $this->getAilisiCookie();
$strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
$CookieJar = CookieJar::fromArray($arrCookie, $strHost);
$strSiteUrl = $this->getAilisiDomain();
$strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
if (strpos($strCover, 'http') === false) {
$strCover = $strSiteUrl . $strCover;
}
$strCoverUri = $strCover;
try {
$strCoverUri = "";
$strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
$arrCover = [
'code' => 'AI_LI_SI_COVER',
// 'uri' => getUriByUrl($strCover),
'uri' => $strCoverUri,
];
$arrXiaoShuoInfo = [
'xsxq_feng_mian' => json_encode($arrCover),
];
$XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
} catch (\Throwable $t) {
$strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
echo $strErr;
}
} catch (\Throwable $T) {
throw $T;
}
}
// public function getNovelInfo($arrData)
// {
// $QueueManage = $this->QueueManage;
// $Client = $this->Client;
// $strSiteUrl = $this->getBiquxsDomain();
// $strUrl = 'http://www.biquxs.com/book/' . $arrData['xs_source_id'] ; //'http://www.biquxs.com/book/20053';
// $intXiaoShuoSourceId = $arrData['xs_source_id']; //20053;
// $intXiaoShuoSourceSeoId = $arrData['xs_source_seo_id']; //1 ;
// try {
// $arrCookie = $this->getAilisiCookie();
// $strHost = getDomainFromUrl($strUrl);
// $CookieJar = CookieJar::fromArray($arrCookie, $strHost);
// $proxy = getRandomProxies();
// $userAgent = getRandomUserAgent();
// $Response = $Client->request('GET', $strUrl, [
// 'headers' => [
// 'User-Agent' => $userAgent,
// 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
// 'Accept-Language' => 'en-US,en;q=0.5',
// ],
// 'cookies' => $CookieJar,
// // 'proxy' => $proxy,
// 'timeout' => 30,
// ]);
// $strResult = (string)$Response->getBody();
// $QueryList = QueryList::html($strResult);
// // var_dump($QueryList);
// // 提取所有 <meta> 标签的属性
// $result = $QueryList->find('meta[property^="og:"]')->map(function ($item) {
// return [
// 'property' => $item->attr('property'),
// 'content' => $item->attr('content'),
// ];
// });
// // 打印结果
// // print_r($result->all());
// $strZuoZhe = '';
// $strMingZi = '';
// $strLastDate = '';
// $strJieShao = '';
// $strCover = '';
// $strFenlei = '';
// $strZiShu = 0;
// $strZhuangTai = $QueryList->find('#info p')->eq(1)->text();
// $strZhuangTai = getStringAfterWord($strZhuangTai, '状态:');
// foreach ($result as $item) {
// switch ($item['property']) {
// case 'og:title':
// $strMingZi = $item['content'];
// break;
// case 'og:description':
// $strJieShao = $item['content'];
// break;
// case 'og:image':
// $strCover = $item['content'];
// break;
// case 'og:book:category':
// $strFenlei = $item['content'];
// break;
// case 'og:book:author':
// $strZuoZhe = $item['content'];
// break;
// case 'og:book:update_time':
// $strLastDate = $item['content'];
// break;
// }
// }
// $strLastDate = trim((string)$strLastDate);
// if (!isValidDateTime($strLastDate)) {
// $strLastDate = date('Y-m-d H:i:s');
// }
// $arrTag = [];
// if (strpos($strCover, 'http') === false) {
// $strCover = $strSiteUrl . $strCover;
// }
// $strCoverUri = $strCover;
// try {
// $strCoverUri = "";
// $strCoverUri = ImageProcessor::getInstance()->downloadImage( $intXiaoShuoSourceId,$strCover, 'xs');
// } catch (\Throwable $t) {
// $strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
// echo $strErr;
// }
// $arrCover = [
// 'code' => 'BI_QU_XS_COVER',
// // 'uri' => getUriByUrl($strCover),
// 'uri' => $strCoverUri,
// ];
// $strFenleiIId = 1 ;
// switch ($strFenlei) {
// case '玄幻小说':
// $strName = "玄幻";
// $strFenleiIId = 1;
// break;
// case '修真小说':
// $strName = "修真";
// $strFenleiIId = 2;
// break;
// case '都市小说':
// $strName = "都市";
// $strFenleiIId = 3;
// break;
// case '历史小说':
// $strName = "历史";
// $strFenleiIId = 4;
// break;
// case '网游小说':
// $strName = "网游";
// $strFenleiIId = 5;
// break;
// case '科幻小说':
// $strName = "科幻";
// $strFenleiIId = 6;
// break;
// case '女频小说':
// $strName = "女频";
// $strFenleiIId = 7;
// break;
// case '其它小说':
// $strName = "其它";
// $strFenleiIId = 8;
// break;
// default:
// $strName = "其它";
// $strFenleiIId = 8;
// break;
// }
// $arrXiaoShuoInfo = [
// 'xsxq_ming_zi' => $strMingZi,
// 'xsxq_zuozhe' => $strZuoZhe , //$arrData['xiaoshuo_zuozhe'],
// 'xsfl_id' => $strFenleiIId,
// 'xsxq_zhuang_tai' => $strZhuangTai,
// 'xsxq_zi_shu' => $strZiShu,
// 'xsxq_jie_shao' => $strJieShao,
// 'xsxq_feng_mian' => json_encode($arrCover),
// 'xsxq_geng_xin_shi_jian' => $strLastDate,
// 'xsxq_tag' => json_encode($arrTag, JSON_UNESCAPED_UNICODE),
// 'xsxq_source_id' => $intXiaoShuoSourceId,
// 'xsxq_source_seo_id' => $intXiaoShuoSourceId.'1',
// 'xsxq_source_code' => 'BIQU_XIAOSHUO_' . $intXiaoShuoSourceId . '_' . $intXiaoShuoSourceSeoId,
// ];
// // print_r($arrXiaoShuoInfo);
// var_dump($arrXiaoShuoInfo['xsxq_source_code']);
// $XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
// $arrZhangjie = [];
// $intChapterIndex = 0; // 定义一个计数器变量
// // 检查是否找到元素
// if ($QueryList->find('.listmain a')->count() > 0) {
// $QueryList->find('.listmain a')->map(function ($ZhangJie) use (&$arrZhangjie, &$intChapterIndex) {
// echo "Processing index $intChapterIndex: " . $ZhangJie->text() . PHP_EOL;
// // 从索引6开始
// if ($intChapterIndex >= 5) {
// $arrZhangjie[] = [
// 'mingzi' => $ZhangJie->text(),
// 'url' => $ZhangJie->attr('href'),
// ];
// }
// $intChapterIndex++;
// });
// // 输出最终结果
// var_dump($arrZhangjie);
// } else {
// echo "No elements found for .listmain a" . PHP_EOL;
// }
// //unset($QueryList);
// // 获取最大章节索引
// $intMaxXiaoShuoZhangJiePaixu = XiaoShuoZhangJieModel::where('xsxq_id', $intXiaoShuoSourceId)
// ->max('xszj_pai_xu'); // 获取最大值
// var_dump('获取小说章节最大值-'.$intMaxXiaoShuoZhangJiePaixu);
// // 如果没有结果max 返回 null可以设置默认值
// $intMaxXiaoShuoZhangJiePaixu = $intMaxXiaoShuoZhangJiePaixu ?? 0;
// foreach ($arrZhangjie as $intZhangJieNum => $arrZhangjieOne) {
// var_dump($intZhangJieNum);
// // 如果数据库里的章节最大索引大于当前索引,说明已经入库,不需要入队列了
// if($intMaxXiaoShuoZhangJiePaixu > $intZhangJieNum){
// var_dump("小说章节已经入库,不再推送任务");
// continue;// 如果任务已存在,直接跳过 break
// }
// $strZhangJieUrl = $strSiteUrl . $arrZhangjieOne['url'];
// $strZhangJieId = extractFilename($strZhangJieUrl);
// # 'AILISI_XIAOSHUO_ZHANGJIE_小说源id_小说源章节id'
// $strXszjSourceCode = 'AILISI_XIAOSHUO_ZHANGJIE_'. $XiaoShuoXiangQingModel->xsxq_source_id . '_' . $strZhangJieId;
// $arrTask = [
// 'callback' => [self::class, 'getNovelReader'],
// 'data' => [
// 'xszj_source_id' => $strZhangJieId,
// 'xszj_paixu' => $intZhangJieNum,
// 'xszj_name' => $arrZhangjieOne['mingzi'],
// 'xszj_url' => $strZhangJieUrl,
// 'xszj_source_code' => $strXszjSourceCode,
// 'xsxq_source_id' => $XiaoShuoXiangQingModel->xsxq_source_id,
// 'xsfl_id' => $strFenleiIId,
// ]
// ];
// $QueueManage->set($arrTask);
// }
// var_dump("章节任务投递成功");
// } catch (\Throwable $T) {
// throw $T;
// }
// }
// public function getNovelFengMian($arrData)
// {
// //var_dump('getNovelFengMian');
// //var_dump($arrData);
// $Client = $this->Client;
// $QueueManage = $this->QueueManage;
// // 获取 Redis 实例
// $redis = Cache::store('redis')->handler();
// $intXiaoShuoSourceId = $arrData['xiaoshuo_id'];
// $intXiaoShuoSourceSeoId = $arrData['xiaoshuo_seo_id'];
// $redisKey = "task:novel_source_id:" . $intXiaoShuoSourceId;
// try {
// $arrCookie = $this->getAilisiCookie();
// $strHost = getDomainFromUrl($arrData['xiaoshuo_url']);
// $CookieJar = CookieJar::fromArray($arrCookie, $strHost);
// $strSiteUrl = $this->getAilisiDomain();
// $strCover = $QueryList->find('#fmimg img')->eq(0)->attr("src");
// if (strpos($strCover, 'http') === false) {
// $strCover = $strSiteUrl . $strCover;
// }
// $strCoverUri = $strCover;
// try {
// $strCoverUri = "";
// $strCoverUri = ImageProcessor::getInstance()->downloadAndEncryptImage($strCover, 'xs');
// $arrCover = [
// 'code' => 'AI_LI_SI_COVER',
// // 'uri' => getUriByUrl($strCover),
// 'uri' => $strCoverUri,
// ];
// $arrXiaoShuoInfo = [
// 'xsxq_feng_mian' => json_encode($arrCover),
// ];
// $XiaoShuoXiangQingModel = XiaoShuoXiangQingModel::addXiaoShuoXiangQing($arrXiaoShuoInfo);
// } catch (\Throwable $t) {
// $strErr = sprintf("采集[%s]小说图片错误,异常:%s", $strCover, $t->getMessage());
// echo $strErr;
// }
// } catch (\Throwable $T) {
// throw $T;
// }
// }
// public function getNovelReader($arrData)
// {
// var_dump('getNovelReader');
// var_dump($arrData['xszj_url']);
// $Client = $this->Client;
// $strXszjSourceCode = $arrData['xszj_source_code'];
// $strZhangJieUrl = $arrData['xszj_url'];
// $intZhangJiePaiXu = $arrData['xszj_paixu'];
// $intFenleiId = $arrData['xsfl_id'];
// $intXiaoShuoSourceID = $arrData['xsxq_source_id'];
// $strZhangJieSourceId = $arrData['xszj_source_id'];
// $strZhangJieName = $arrData['xszj_name'];
// try {
// $arrCookie = $this->getAilisiCookie();
// $strHost = getDomainFromUrl($strZhangJieUrl);
// $CookieJar = CookieJar::fromArray($arrCookie, $strHost);
// if (XiaoShuoZhangJieModel::checkZhangJieExists($strXszjSourceCode)) {
// return true;
// }
// $proxy = getRandomProxies();
// $userAgent = getRandomUserAgent();
// $Response = $Client->request('GET', $strZhangJieUrl, [
// 'headers' => [
// 'User-Agent' => $userAgent,
// 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
// 'Accept-Language' => 'en-US,en;q=0.5',
// ],
// 'cookies' => $CookieJar,
// // 'proxy' => $proxy,
// 'timeout' => 30,
// ]);
// $strResult = (string)$Response->getBody();
// unset($Response);
// $ZhangJieQueryList = QueryList::html($strResult);
// // 获取原始 HTML
// $strNeiRong = $ZhangJieQueryList->find('#content')->eq(0)->html();
// // 解码 HTML 实体
// $strNeiRong = html_entity_decode($strNeiRong, ENT_QUOTES, 'UTF-8');
// // 去掉 <p> 标签中的 class="content_detail" 属性
// $strNeiRong = preg_replace('/<p\s+class="content_detail"/i', '<p', $strNeiRong);
// // 清理多余的 HTML 标签
// $strNeiRong = strip_tags($strNeiRong, '<p>');
// // 替换不间断空格 (\xc2\xa0) 和 &nbsp; 为普通空格
// $strNeiRong = preg_replace('/\xc2\xa0/', ' ', $strNeiRong); // 替换 UTF-8 不间断空格
// $strNeiRong = preg_replace('/&nbsp;/', ' ', $strNeiRong); // 替换 &nbsp;
// // 清理多余空格和换行符
// $strNeiRong = preg_replace('/\s+/', ' ', $strNeiRong);
// $strNeiRong = preg_replace('/<p>\s+/', '<p>', $strNeiRong); // 清理 <p> 标签内部多余空格
// $strNeiRong = preg_replace('/\s+<\/p>/', '</p>', $strNeiRong); // 清理 <p> 标签结尾多余空格
// // 输出结果
// // var_dump($strNeiRong);
// # '/novel/123yqw/分类id/小说源id/小说源章节id.txt'
// $strNeiRongTxtPath = config("filesystem.novel").'/novel/biquxs/'.$intFenleiId.'/'.$intXiaoShuoSourceID.'/'.$strZhangJieSourceId.'.txt';
// //$strNeiRongTxtPath = "/www/novel/123yqw/1/11/111.txt";
// // 调用函数
// $result = saveCompressAndDeleteTxt($strNeiRongTxtPath, $strNeiRong);
// // 输出状态
// if ($result['status']) {
// var_dump("Success: " . $result['message']) ;
// } else {
// var_dump("Error: " . $result['message']) ;
// }
// $arrXiaoShuoZhangJie = [
// 'xsxq_id' => $intXiaoShuoSourceID,
// 'xszj_pai_xu' => $intZhangJiePaiXu,
// 'xszj_ming_zi' => $strZhangJieName,
// 'xszj_nei_rong' => $strNeiRongTxtPath,
// 'xszj_source_id' => $strZhangJieSourceId,
// 'xszj_source_code' => $strXszjSourceCode,
// ];
// XiaoShuoZhangJieModel::addXiaoShuoZhangJie($arrXiaoShuoZhangJie);
// unset($ZhangJieQueryList);
// // 延时 3 秒
// //sleep(3);
// } catch (\Throwable $T) {
// throw $T;
// }
// }
}

View File

@@ -1,50 +0,0 @@
<?php
namespace app\task\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument;
use think\facade\Db;
class InsertSeoWordsCommand extends Command
{
protected function configure()
{
// 配置命令的名称和参数
$this->setName('insert:seowords')
->setDescription('Insert SEO words from a text file into the seo_keywords table')
->addArgument('file', Argument::REQUIRED, 'The path of the text file');
}
protected function execute(Input $input, Output $output)
{
// 获取传递的文件路径参数
$file = $input->getArgument('file');
// 检查文件是否存在
if (!file_exists($file)) {
$output->writeln("The file does not exist.");
return;
}
// 读取文件内容
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// 遍历每一行,插入数据库
foreach ($lines as $line) {
// 假设每一行是以逗号分隔的字段值,例如:关键词标题,状态,HTML路径
// list($title, $status, $htmlPath) = explode(',', $line);
$title = $line;
// 插入数据到 seo_keywords 表
Db::name('seo_keywords')->insert([
'sw_title' => trim($title),
]);
$output->writeln("Inserted: $title");
}
$output->writeln("Data insertion completed.");
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare (strict_types = 1);
namespace app\task\core;
class Rout
{
static public function httpDispense(\Swoole\Http\Request $Request, \Swoole\Http\Response $Response)
{
// print_r($Request->getData());
// print_r($Request->server);
# 简单的HTTP服务
$Response->status(999,'Hei Guys ~');
$Response->header("Content-Type", "text/html; charset=utf-8");
$Response->end("<h1>Hello reptile~. #".rand(1000, 9999)."</h1>");
}
static public function tcpDispense(\Swoole\Server $server, $fd, $reactor_id, $mixedData)
{
# 简单的HTTP服务
print_r($mixedData);
}
static public function test()
{
var_dump(date('Y-m-d H:i:s'));
return;
}
}

View File

@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\core;
use app\task\logic\SystemLogic;
class ScheduledTasks
{
static public function hander($arrProcessTask = [])
{
SystemLogic::destructConnectSource();
// while(true){
call_user_func($arrProcessTask['callback'], $arrProcessTask['param']);
sleep($arrProcessTask['execution_interval']);
// }
// \Swoole\Timer::tick($arrProcessTask['execution_interval']*1000, $arrProcessTask['callback'], $arrProcessTask['param']);
// \Swoole\Event::wait();
}
}

View File

@@ -1,70 +0,0 @@
<?php
declare(strict_types=1);
namespace app\task\logic;
use app\model\GuangGaoFenZuModel;
use app\model\GuangGaoModel;
use app\model\GuangGaoPeiZhiModel;
use GuzzleHttp\Client;
/**
* @mixin think\Model
*/
class AdTask
{
/**
* Undocumented variable
*
* @var \GuzzleHttp\Client
*/
protected $Client = NULL;
/**
* Undocumented variable
*
* @var \app\task\core\TaskCore
*/
protected $TaskCore = NULL;
protected $arrCaiJiPeiZhi = [];
public function __construct()
{
$this->Client = new Client();
}
public function pullAdBySourceSite()
{
$intOpen = GuangGaoPeiZhiModel::getValByCode('GUANG_GAO_TONG_BU_KAI_GUAN');
if ($intOpen != 1) {
return false;
}
$strUrl = GuangGaoPeiZhiModel::getValByCode('GUANG_GAO_TONG_BU_DI_ZHI');
$strResult = $this->Client->request('GET', $strUrl);
$strResult = (string)$strResult->getBody();
$arrData = json_decode($strResult, true);
if (!is_array($arrData) || empty($arrData)) {
return false;
}
if ($arrData['code'] != 1000) {
return false;
}
GuangGaoModel::where('gg_id', '>', 0)->delete();
GuangGaoFenZuModel::where('ggfz_id', '>', 0)->delete();
GuangGaoFenZuModel::insertAll($arrData['data']['ggfz']);
GuangGaoModel::insertAll($arrData['data']['gg']);
GuangGaoModel::flushCache();
}
}

View File

@@ -2,9 +2,10 @@
declare(strict_types=1);
namespace app\task\core;
namespace app\task\module;
use app\task\logic\SystemLogic;
use minserver\ProcessSanitizer;
use minserver\QueueManage;
class Listen
{
@@ -16,7 +17,7 @@ class Listen
*/
static public function innerConsume(\Swoole\Process $Process)
{
return self::innerConsumeCore($Process, 1);
return self::innerConsumeCore(1);
}
@@ -28,7 +29,7 @@ class Listen
*/
static public function innerConsume02(\Swoole\Process $Process)
{
return self::innerConsumeCore($Process, 2);
return self::innerConsumeCore(2);
}
/**
@@ -37,19 +38,18 @@ class Listen
* @param \Swoole\Process $Process
* @return void
*/
static private function innerConsumeCore(\Swoole\Process $Process, int $intIndex = 1)
static private function innerConsumeCore(int $intIndex = 1)
{
Service::$Process = $Process;
SystemLogic::destructConnectSource();
ProcessSanitizer::destructConnectSource();
$arrConfig = config('task.queue');
$intLimit = $arrConfig[$intIndex]['exec_num'];
$TaskCore = new TaskCore($intIndex);
$QueueManage = new QueueManage($intIndex);
return self::excuteTask($TaskCore, $intLimit);
return self::excuteTask($QueueManage, $intLimit);
}
/**
@@ -58,12 +58,12 @@ class Listen
* @param \Swoole\Process $Process
* @return void
*/
static private function excuteTask(TaskCore $TaskCore, $intLimit)
static private function excuteTask(QueueManage $QueueManage, $intLimit)
{
while ($intLimit > 0) {
$intLimit--;
try {
$strData = $TaskCore->get();
$strData = $QueueManage->get();
if (empty($strData)) {
sleep(1);
continue;

View File

@@ -5,32 +5,18 @@ declare(strict_types=1);
namespace app\task\module;
use app\model\PlanTaskModel;
use app\task\collection\ailisi\XiaoShuoCol;
use app\task\collection\biquxs\BiquxsXiaoShuoCol;
use app\task\collection\ccc5\XiaoShuo5cccCol;
use app\task\collection\novel\Zw630XiaoShuoCol;
use app\task\collection\novelone\NovelJiuYuFanXianCol;
use app\task\collection\novelone\NovelWenXueGuanCol;
use app\task\collection\tianlai\TianLaiXiaoShuoCol;
use app\task\collection\seo\GenerateSiteMapCol;
use app\task\collection\seo\GenerateSiteMapNovel;
use app\task\collection\seo\GenerateSiteMapNovelZw;
use app\task\collection\seo\GenerateSiteMapNovelSk;
use app\task\collection\visitlogs\ContentStatsCol;
use app\task\collection\dadi\DaDiDianyingCol;
use app\task\collection\heimuer\HeiMuErYingShiCol;
use app\task\collection\yzzy\YouZhiYingShiCol;
use app\task\core\TaskCore;
use app\task\logic\SystemLogic;
use app\task\collection\zw630\Zw630Col;
use minserver\QueueManage;
use minserver\ProcessSanitizer;
class PlanTask
{
public static function scanPlanTask($arrData)
{
SystemLogic::destructConnectSource();
ProcessSanitizer::destructConnectSource();
$PlanTaskAll = PlanTaskModel::where('pt_enable', 1)->where('site_id', config('app.default_app_id'))->select();
$PlanTaskAll = PlanTaskModel::where('pt_enable', 1)->select();
foreach ($PlanTaskAll as $PlanTask) {
@@ -42,50 +28,8 @@ class PlanTask
switch ($PlanTask->pt_code) {
case 'PULL_XIAOSHUO':
self::pullXiaoShuo();
break;
case 'PULL_TIANLAIXIAOSHUO':
self::pullTianLaiXiaoShuo();
break;
case 'PULL_BIQUXSXIAOSHUO':
self::pullBiquxsXiaoShuo();
break;
case 'PULL_5CCCXIAOSHUO':
self::pull5cccXiaoShuo();
break;
case 'PULL_DADI_DIANYHHING':
self::pullDadiYingshi();
break;
case 'PULL_HEI_MUER':
self::pullHeiMuEr();
break;
case 'PULL_YOUZHI':
self::pullYouZhiZiYuan();
break;
case 'PULL_TONJI_HUIZON':
self::AddTongJiHuizon();
break;
case 'GENERATE_SITEMAP':
self::generateSiteMap();
break;
case 'NOVEL_GENERATE_SITEMAP':
self::generateNovelSiteMap();
break;
case 'NOVELZW_GENERATE_SITEMAP':
self::generateSiteMapNovelZw();
break;
case 'NOVEL_SK_GENERATE_SITEMAP':
self::generateSiteMapNovelSk();
break;
case 'PULL_630ZWXIAOSHUO':
self::pull630ZwXiaoShuo();
break;
case 'PULL_GUICHUIDENG_XIAOSHUO':
self::pullGuiChuiDengJiuYuFanXianXiaoShuo();
break;
case 'PULL_WENXUEGUAN_XIAOSHUO':
self::pullWenXueGuangXianXiaoShuo();
case 'PULL_630_ZW_NOVEL':
self::pull630ZwNovel();
break;
default:
@@ -99,260 +43,14 @@ class PlanTask
*
* @return void
*/
public static function pullWenXueGuangXianXiaoShuo()
public static function pull630ZwNovel()
{
$arrTask = [
'callback' => [NovelWenXueGuanCol::class, 'pullXiaoShuo'],
'callback' => [Zw630Col::class, 'pull630ZwNovel'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
$QueueManage = new QueueManage();
$QueueManage->set($arrTask);
}
/**
* 拉取鬼吹灯小说-九域凡仙
*
* @return void
*/
public static function pullGuiChuiDengJiuYuFanXianXiaoShuo()
{
$arrTask = [
'callback' => [NovelJiuYuFanXianCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取小说
*
* @return void
*/
public static function pull630ZwXiaoShuo()
{
$arrTask = [
'callback' => [Zw630XiaoShuoCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 生成地图-小说
*
* @return void
*/
public static function generateNovelSiteMap()
{
$arrTask = [
'callback' => [GenerateSiteMapNovel::class, 'generate'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 生成地图-小说 novelzw 模板
*
* @return void
*/
public static function generateSiteMapNovelZw()
{
$arrTask = [
'callback' => [GenerateSiteMapNovelZw::class, 'generate'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 生成地图-小说 novelzw 模板
*
* @return void
*/
public static function generateSiteMapNovelSk()
{
$arrTask = [
'callback' => [GenerateSiteMapNovelSk::class, 'generate'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 生成地图-视频
*
* @return void
*/
public static function generateSiteMap()
{
$arrTask = [
'callback' => [GenerateSiteMapCol::class, 'generate'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取优质资源
*
* @return void
*/
public static function AddTongJiHuizon()
{
$arrTask = [
'callback' => [ContentStatsCol::class, 'run'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取优质资源
*
* @return void
*/
public static function AddVisitLogs()
{
$arrTask = [
'callback' => [YouZhiYingShiCol::class, 'add'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取优质资源
*
* @return void
*/
public static function pullYouZhiZiYuan()
{
$arrTask = [
'callback' => [YouZhiYingShiCol::class, 'pullYouZhiYingshi'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取黑木耳
*
* @return void
*/
public static function pullHeiMuEr()
{
$arrTask = [
'callback' => [HeiMuErYingShiCol::class, 'pullDadiYingshi'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取大地影视
*
* @return void
*/
public static function pullDadiYingshi()
{
$arrTask = [
'callback' => [DaDiDianyingCol::class, 'pullDadiYingshi'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取小说
*
* @return void
*/
public static function pull5cccXiaoShuo()
{
$arrTask = [
'callback' => [XiaoShuo5cccCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取小说
*
* @return void
*/
public static function pullXiaoShuo()
{
$arrTask = [
'callback' => [XiaoShuoCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取小说
*
* @return void
*/
public static function pullBiquxsXiaoShuo()
{
$arrTask = [
'callback' => [BiquxsXiaoShuoCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
/**
* 拉取小说
*
* @return void
*/
public static function pullTianLaiXiaoShuo()
{
$arrTask = [
'callback' => [TianLaiXiaoShuoCol::class, 'pullXiaoShuo'],
'data' => []
];
$TaskCore = new TaskCore();
$TaskCore->set($arrTask);
}
}

View File

@@ -33,7 +33,8 @@
"fakerphp/faker": "^1.23",
"aws/aws-sdk-php": "^3.337",
"league/flysystem": "^1.1",
"league/flysystem-aws-s3-v3": "^1.0"
"league/flysystem-aws-s3-v3": "^1.0",
"mongodb/mongodb": "^1.21"
},
"require-dev": {
"topthink/think-dumper": "^1.0",

View File

@@ -5,7 +5,7 @@
return [
// 指令定义
'commands' => [
'task' => 'app\task\command\Task',
'db:manage' => 'app\task\command\DatabaseCommand',
'task' => 'minserver\ServerConsole',
'db:manage' => 'db\DatabaseManage',
],
];

View File

@@ -59,5 +59,6 @@ return [
],
// 更多的数据库配置信息
],
];

19
code/config/mongodb.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
return [
// 服务器地址
'hostname' => env('MONGO_HOST', '127.0.0.1'),
// 端口
'hostport' => env('MONGO_PORT', '3306'),
// 用户名
'username' => env('MONGO_USER', 'root'),
// 密码
'password' => env('MONGO_PASSWORD', ''),
// 数据库名
'database' => env('MONGO_DB', ''),
];

View File

@@ -43,14 +43,14 @@ return [
[
'Name' => 'Inner Consume',
'Num' => env('TASK_PROCESS_NUM_01', 4),
'callback' => [app\task\core\Listen::class, 'innerConsume'],
'callback' => [app\task\module\Listen::class, 'innerConsume'],
],
# 内部循环任务进程组 优先队列消费者
[
'Name' => 'Inner Consume',
'Num' => env('TASK_PROCESS_NUM_02', 2),
'callback' => [app\task\core\Listen::class, 'innerConsume02'],
'callback' => [app\task\module\Listen::class, 'innerConsume02'],
],
],

View File

@@ -1,8 +1,8 @@
-- MySQL dump 10.13 Distrib 8.0.32, for Linux (x86_64)
-- MySQL dump 10.13 Distrib 8.0.41, for Linux (x86_64)
--
-- Host: 127.0.0.1 Database: 8X
-- Host: 127.0.0.1 Database: seo
-- ------------------------------------------------------
-- Server version 8.0.32
-- Server version 8.0.41
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
@@ -32,7 +32,7 @@ CREATE TABLE `admin_user` (
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`au_id`),
UNIQUE KEY `au_name` (`au_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -49,10 +49,28 @@ CREATE TABLE `cai_ji_pei_zhi` (
`cjpz_description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`cjpz_id`),
KEY `cjpz_code` (`cjpz_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `domain`
--
DROP TABLE IF EXISTS `domain`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `domain` (
`d_id` int NOT NULL AUTO_INCREMENT COMMENT '域名ID',
`d_domain` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '域名',
`t_id` int DEFAULT NULL COMMENT '模板ID',
`d_title` varchar(300) COLLATE utf8mb4_unicode_ci DEFAULT '',
`d_keywords` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`d_description` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`d_id`),
KEY `t_id` (`t_id`),
KEY `d_domain` (`d_domain`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='域名表';
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `guang_gao`
@@ -68,9 +86,13 @@ CREATE TABLE `guang_gao` (
`gg_tu_pian` varchar(500) DEFAULT NULL,
`gg_wen_zi` varchar(500) DEFAULT NULL,
`gg_tiao_zhuan_di_zhi` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`gg_status` int DEFAULT '0',
`gg_sort` int DEFAULT NULL,
`site_id` int DEFAULT '1' COMMENT '站点ID',
PRIMARY KEY (`gg_id`),
KEY `ggfz_id` (`ggfz_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
KEY `ggfz_id` (`ggfz_id`),
KEY `site_id` (`site_id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -84,9 +106,11 @@ CREATE TABLE `guang_gao_fen_zu` (
`ggfz_id` int unsigned NOT NULL AUTO_INCREMENT,
`ggfz_code` varchar(255) DEFAULT NULL,
`ggfz_name` varchar(255) DEFAULT NULL,
`site_id` int DEFAULT '1' COMMENT '站点ID',
PRIMARY KEY (`ggfz_id`),
UNIQUE KEY `ggfz_code` (`ggfz_code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
UNIQUE KEY `ggfz_code` (`ggfz_code`) USING BTREE,
KEY `site_id` (`site_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -101,12 +125,13 @@ CREATE TABLE `guang_gao_pei_zhi` (
`ggpz_code` varchar(255) DEFAULT NULL,
`ggpz_val` text,
`ggpz_description` varchar(255) DEFAULT NULL,
`site_id` int DEFAULT '1' COMMENT '站点ID',
PRIMARY KEY (`ggpz_id`),
KEY `ggpz_code` (`ggpz_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
KEY `ggpz_code` (`ggpz_code`),
KEY `site_id` (`site_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `migrations`
--
@@ -116,7 +141,7 @@ DROP TABLE IF EXISTS `migrations`;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `migrations` (
`version` bigint NOT NULL,
`migration_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`migration_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start_time` timestamp NULL DEFAULT NULL,
`end_time` timestamp NULL DEFAULT NULL,
`breakpoint` tinyint(1) NOT NULL DEFAULT '0',
@@ -124,7 +149,6 @@ CREATE TABLE `migrations` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `plan_task`
--
@@ -139,43 +163,12 @@ CREATE TABLE `plan_task` (
`pt_enable` tinyint unsigned NOT NULL DEFAULT '1',
`pt_limit` int unsigned NOT NULL DEFAULT '0',
`pt_last_exec` int unsigned NOT NULL DEFAULT '0',
`site_id` int DEFAULT '1' COMMENT '站点ID',
PRIMARY KEY (`pt_id`) USING BTREE,
KEY `pt_code` (`pt_code`) USING BTREE,
KEY `pt_enable` (`pt_enable`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `re_sou`
--
DROP TABLE IF EXISTS `re_sou`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `re_sou` (
`rs_id` int unsigned NOT NULL AUTO_INCREMENT,
`rsfz_id` int DEFAULT NULL,
`rs_ming_zi` varchar(255) DEFAULT NULL,
PRIMARY KEY (`rs_id`),
UNIQUE KEY `rs_ming_zi` (`rs_ming_zi`),
KEY `rsfz_id` (`rsfz_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `re_sou_fen_zu`
--
DROP TABLE IF EXISTS `re_sou_fen_zu`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `re_sou_fen_zu` (
`rsfz_id` int unsigned NOT NULL AUTO_INCREMENT,
`rsfz_ming_zi` varchar(255) DEFAULT NULL,
`rsfz_pai_xu` tinyint DEFAULT '1',
PRIMARY KEY (`rsfz_id`),
UNIQUE KEY `rsfz_ming_zi` (`rsfz_ming_zi`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
KEY `pt_enable` (`pt_enable`) USING BTREE,
KEY `site_id` (`site_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -190,84 +183,29 @@ CREATE TABLE `system_config` (
`sc_code` varchar(255) DEFAULT NULL,
`sc_val` text,
`sc_description` text,
PRIMARY KEY (`sc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
`site_id` int DEFAULT '1' COMMENT '站点ID',
PRIMARY KEY (`sc_id`),
KEY `site_id` (`site_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `xiao_shuo_fen_lei`
-- Table structure for table `templates`
--
DROP TABLE IF EXISTS `xiao_shuo_fen_lei`;
DROP TABLE IF EXISTS `templates`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `xiao_shuo_fen_lei` (
`xsfl_id` int unsigned NOT NULL AUTO_INCREMENT,
`xsfl_source_id` varchar(255) DEFAULT NULL,
`xsfl_source_code` varchar(255) DEFAULT NULL,
`xsfl_name` varchar(500) DEFAULT NULL,
PRIMARY KEY (`xsfl_id`),
UNIQUE KEY `xsfl_source_code` (`xsfl_source_code`),
KEY `xsfl_source_id` (`xsfl_source_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `templates` (
`t_id` int NOT NULL AUTO_INCREMENT COMMENT '视图模板ID',
`t_default` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '是否默认模板',
`t_code` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '模板编码',
`t_path` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '模板位置',
PRIMARY KEY (`t_id`),
KEY `t_code` (`t_code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='模板表';
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `xiao_shuo_xiang_qing`
--
DROP TABLE IF EXISTS `xiao_shuo_xiang_qing`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `xiao_shuo_xiang_qing` (
`xsxq_id` int unsigned NOT NULL AUTO_INCREMENT,
`xsxq_source_id` varchar(255) DEFAULT NULL,
`xsxq_source_seo_id` varchar(255) DEFAULT NULL,
`xsfl_id` int DEFAULT NULL,
`xsxq_ming_zi` varchar(255) DEFAULT NULL,
`xsxq_tui_jian` int unsigned DEFAULT '0',
`xsxq_zuozhe` varchar(255) DEFAULT NULL,
`xsxq_zhuang_tai` varchar(255) DEFAULT NULL,
`xsxq_zi_shu` varchar(255) DEFAULT NULL,
`xsxq_jie_shao` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`xsxq_feng_mian` json DEFAULT NULL,
`xsxq_geng_xin_shi_jian` datetime DEFAULT CURRENT_TIMESTAMP,
`xsxq_tag` json DEFAULT NULL,
`xsxq_source_code` varchar(255) DEFAULT NULL,
`xsxq_ren_qi` int unsigned DEFAULT '0',
`xsxq_shou_cang` int unsigned DEFAULT '0',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`xsxq_id`),
UNIQUE KEY `xsxq_source_code` (`xsxq_source_code`),
KEY `xsfl_id` (`xsfl_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `xiao_shuo_zhang_jie`
--
DROP TABLE IF EXISTS `xiao_shuo_zhang_jie`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `xiao_shuo_zhang_jie` (
`xszj_id` int unsigned NOT NULL AUTO_INCREMENT,
`xsxq_id` int DEFAULT NULL,
`xszj_pai_xu` int DEFAULT NULL,
`xszj_ming_zi` varchar(500) DEFAULT NULL,
`xszj_nei_rong` longtext,
`xszj_source_id` varchar(255) DEFAULT NULL,
`xszj_source_code` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`xszj_id`),
UNIQUE KEY `xszj_source_code` (`xszj_source_code`),
KEY `xsxq_id` (`xsxq_id`),
KEY `xszj_pai_xu` (`xszj_pai_xu`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `zi_yuan_duan_dian`
--
@@ -282,7 +220,7 @@ CREATE TABLE `zi_yuan_duan_dian` (
`zydd_domain` varchar(255) DEFAULT NULL,
PRIMARY KEY (`zydd_id`),
KEY `zydd_code` (`zydd_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@@ -294,4 +232,4 @@ CREATE TABLE `zi_yuan_duan_dian` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2024-07-16 0:29:57
-- Dump completed on 2025-03-18 22:53:36

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace app\task\command;
namespace db;
use database\seeders\SeedManager;
use think\console\Command;
@@ -12,7 +12,7 @@ use think\console\Output;
use think\console\input\Option;
use think\facade\Db;
class DatabaseCommand extends Command
class DatabaseManage extends Command
{
protected function configure()
{

View File

@@ -0,0 +1,183 @@
<?php
namespace db\mongo;
use MongoDB\Client;
use MongoDB\Exception\Exception as MongoDBException;
use MongoDB\BSON\UTCDateTime;
class MongoBase
{
private $client;
/**
* Undocumented variable
*
* @var \MongoDB\Database
*/
private $db;
private static $instance;
public static function getInstance(string $uri, string $dbName): self
{
// return [
// 'uri' => 'mongodb://username:password@your_ip:27017',
// 'database' => 'your_database',
// ];
if (!self::$instance) {
self::$instance = new self($uri, $dbName);
}
return self::$instance;
}
/**
* 构造函数,初始化 MongoDB 连接
* @param string $uri MongoDB 连接字符串
* @param string $dbName 数据库名称
*/
public function __construct(string $uri, string $dbName)
{
try {
$this->client = new Client($uri);
$this->db = $this->client->selectDatabase($dbName);
} catch (MongoDBException $e) {
throw new \Exception("MongoDB connection failed: " . $e->getMessage());
}
}
/**
* 获取下一个自增序列值
* @param string $sequenceName 序列名称
* @return int 自增 ID
*/
public function getNextSequence(string $sequenceName): int
{
try {
$counters = $this->db->selectCollection('counters');
$result = $counters->findOneAndUpdate(
['_id' => $sequenceName],
['$inc' => ['sequence_value' => 1]],
[
'upsert' => true,
'returnDocument' => \MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
]
);
return $result->sequence_value ?? 1;
} catch (MongoDBException $e) {
throw new \Exception("Failed to generate sequence: " . $e->getMessage());
}
}
/**
* 插入单条数据
* @param string $collection 集合名称
* @param array $data 数据数组
* @return mixed 插入的 ID
*/
public function insertOne(string $collection, array $data)
{
try {
$coll = $this->db->selectCollection($collection);
$data['created_at'] = new UTCDateTime(); // 自动添加创建时间
$result = $coll->insertOne($data);
return $result->getInsertedId();
} catch (MongoDBException $e) {
throw new \Exception("Insert failed: " . $e->getMessage());
}
}
/**
* 插入多条数据
* @param string $collection 集合名称
* @param array $data 多条数据数组
* @return array 插入的 ID 列表
*/
public function insertMany(string $collection, array $data)
{
try {
$coll = $this->db->selectCollection($collection);
foreach ($data as &$item) {
$item['created_at'] = new UTCDateTime();
}
$result = $coll->insertMany($data);
return $result->getInsertedIds();
} catch (MongoDBException $e) {
throw new \Exception("Insert many failed: " . $e->getMessage());
}
}
/**
* 查询单条数据
* @param string $collection 集合名称
* @param array $filter 查询条件
* @param array $options 查询选项
* @return ?object 查询结果
*/
public function findOne(string $collection, array $filter = [], array $options = []): ?object
{
try {
$coll = $this->db->selectCollection($collection);
return $coll->findOne($filter, $options);
} catch (MongoDBException $e) {
throw new \Exception("Find one failed: " . $e->getMessage());
}
}
/**
* 查询多条数据
* @param string $collection 集合名称
* @param array $filter 查询条件
* @param array $options 查询选项
* @return array 查询结果
*/
public function findMany(string $collection, array $filter = [], array $options = []): array
{
try {
$coll = $this->db->selectCollection($collection);
$cursor = $coll->find($filter, $options);
return iterator_to_array($cursor);
} catch (MongoDBException $e) {
throw new \Exception("Find many failed: " . $e->getMessage());
}
}
/**
* 更新单条数据
* @param string $collection 集合名称
* @param array $filter 查询条件
* @param array $update 更新内容
* @param array $options 更新选项
* @return int 受影响的文档数
*/
public function updateOne(string $collection, array $filter, array $update, array $options = []): int
{
try {
$coll = $this->db->selectCollection($collection);
$update['$set']['updated_at'] = new UTCDateTime(); // 自动添加更新时间
$result = $coll->updateOne($filter, $update, $options);
return $result->getModifiedCount();
} catch (MongoDBException $e) {
throw new \Exception("Update one failed: " . $e->getMessage());
}
}
/**
* 删除数据
* @param string $collection 集合名称
* @param array $filter 查询条件
* @return int 删除的文档数
*/
public function delete(string $collection, array $filter): int
{
try {
$coll = $this->db->selectCollection($collection);
$result = $coll->deleteMany($filter);
return $result->getDeletedCount();
} catch (MongoDBException $e) {
throw new \Exception("Delete failed: " . $e->getMessage());
}
}
}

View File

@@ -1,15 +1,12 @@
<?php
declare (strict_types = 1);
namespace app\task\logic;
namespace minserver;
use think\Container;
use think\facade\Db;
/**
* @mixin think\Model
*/
class SystemLogic
class ProcessSanitizer
{
static public function reloadRedis()
{

View File

@@ -2,11 +2,11 @@
declare(strict_types=1);
namespace app\task\core;
namespace minserver;
use think\facade\Cache;
class TaskCore
class QueueManage
{
public $strQueueName = '';
@@ -28,8 +28,6 @@ class TaskCore
public function set($arrData)
{
$strData = json_encode($arrData);
// 打印调试信息
//\think\facade\Log::info('TaskCore set: '.$strData );
return Cache::store('redis')->rpush($this->strQueueName, $strData);
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace minserver;
class Rout
{
static public function httpDispense(\Swoole\Http\Request $Request, \Swoole\Http\Response $Response)
{
$Response->status(999, 'Hei Guys ~');
$Response->header("Content-Type", "text/html; charset=utf-8");
$Response->end("<h1>Hello reptile~. #" . rand(1000, 9999) . "</h1>");
}
static public function tcpDispense(\Swoole\Server $server, $fd, $reactor_id, $mixedData) {}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace minserver;
use minserver\ProcessSanitizer;
class ScheduledTasks
{
static public function hander($arrProcessTask = [])
{
ProcessSanitizer::destructConnectSource();
call_user_func($arrProcessTask['callback'], $arrProcessTask['param']);
sleep($arrProcessTask['execution_interval']);
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace app\task\command;
namespace minserver;
use think\console\Command;
use think\console\Input;
@@ -10,7 +10,7 @@ use think\console\input\Argument;
use think\console\Output;
use think\console\input\Option;
class Task extends Command
class ServerConsole extends Command
{
private $arrArguments = [
'action' => ['start', 'stop', 'restart', 'status',],
@@ -19,7 +19,7 @@ class Task extends Command
];
private $arrReflection = [
\app\task\core\Core::class,
\minserver\ServerManage::class,
];
protected function configure()

View File

@@ -2,9 +2,9 @@
declare(strict_types=1);
namespace app\task\core;
namespace minserver;
class Service
class ServerCore
{
private $arrConfig;
@@ -31,7 +31,7 @@ class Service
private function serHttpConfig()
{
$this->Server->set($this->filterConfig());
$this->Server->on('request', [\app\task\core\Rout::class, 'httpDispense']);
$this->Server->on('request', [\minserver\Rout::class, 'httpDispense']);
}
private function filterConfig()
@@ -48,7 +48,7 @@ class Service
private function serTcpConfig()
{
$this->Server->set($this->filterConfig());
$this->Server->on('receive', [\app\task\core\Rout::class, 'tcpDispense']);
$this->Server->on('receive', [\minserver\Rout::class, 'tcpDispense']);
}
private function createServer()

View File

@@ -2,9 +2,9 @@
declare(strict_types=1);
namespace app\task\core;
namespace minserver;
class Core
class ServerManage
{
static $HttpService;
@@ -99,7 +99,7 @@ class Core
foreach (config('task.scheduled_tasks_pool') as $arrProcessTask) {
if ($arrProcessTask['status']) {
$Process = new \Swoole\Process(function () use ($arrProcessTask) {
call_user_func([\app\task\core\ScheduledTasks::class, 'hander'], $arrProcessTask);
call_user_func([\minserver\ScheduledTasks::class, 'hander'], $arrProcessTask);
});
self::$HttpService->getServer()->addProcess($Process);
}
@@ -124,6 +124,6 @@ class Core
{
$arrHttpServiceConfig = array_merge(config('task.service'), self::$arrDynamicConfig);
self::$HttpService = Service::instance($arrHttpServiceConfig);
self::$HttpService = ServerCore::instance($arrHttpServiceConfig);
}
}