某個章節名 / CSS 選擇器【選擇器後可跟 >> 傳入 item 處理】 **@@** 抓取到 URL 的正規表示式匹配 **@@** 正規表示式替換 URL **@@** 根據爬取返回內容 data 進行處理並回傳最終文本
#### 内頁處理範例
假設章節元素為 `a.links`
+ 使用 iframe 處理内頁内容
`a.links@@@@@@iframe:`
- iframe 添加 sandbox
`a.links@@@@@@iframe:sandbox:{allow-same-origin}`
- iframe 添加初始化程式碼
`a.links@@@@@@iframe:init:{win.top=win.self}`
+ 自訂内頁中分頁抓取方式
- 透過選擇器抓取
`a.links@@@@@@next:{a.next}`
- 透過程式碼生成
`a.links@@@@@@next:{return await getNextElement()}` 可以用多層 `{}` 來避免程式碼中出現大括號產生的問題
### 自訂下載範例,打開目錄頁點擊【自訂下載】粘貼後使用,僅爲規則實例引導,有出入請自行修改
+ [📕po18](https://www.po18.tw/books/755779/articles)
> 章節的選擇器為 `.l_chaptname>a` ,輸入並下載後發現通過 url 無法下載正文內容,正文是 ajax 通過 articlescontent 下載的。此時可後接 `@@articles@@articlescontent` (@@ 分隔) 將章節 url 中的 articles 替換為 articlescontent 。 `.l_chaptname>a@@articles@@articlescontent` 粘貼進命令菜單即可下載。其中第一個 articles 可使用正規表示式,例如 `@@articles(\d+)@@$1content` 代表將連結中的「articles1」「articles2」等替換為「1content」「2content」。
``` css
.l_chaptname>a@@articles@@articlescontent
```
> 如果需要下載已購買的vip章節,用這個規則
``` javascript
a.btn_L_blue>>let a=document.createElement("a");a.innerText=item.parentNode.parentNode.querySelector('.l_chaptname').innerText;a.href=item.href;return a;@@articles@@articlescontent
```
+ [📕pixiv](https://www.pixiv.net/novel/series/7807554)
> p站小說的章節選擇器為`main>section ul>li div>a`,無需替換連結,因此後兩項留空。有6個@了 😂。正文在meta裡,需要自定義代碼提取meta-preload數據的content項。其中 "doc" 代表抓取網頁的document對象,若返回的是純文本,則用 `doc.body.innerText` 獲取。
``` javascript
main>section ul>li div>a@@@@@@var noval=JSON.parse(doc.querySelector("#meta-preload-data").content).novel;noval[Object.keys(noval)[0]].content;
```
+ [📕紅薯中文網](https://g.hongshu.com/chapterlist/91735.do)
> 這個站沒有目錄連結,此時可以遍歷標籤自己創建目錄連結下載
``` javascript
ul#lists>li>>let href=item.getAttribute("onclick").replace(/.*(http.*html).*/,"$1"),innerText=item.querySelector("span").innerText;return {href:href,innerText:innerText};@@@@@@let rdtext=data.querySelector('div.rdtext');let sc=data.querySelector('div.ewm+script');if(sc&&rdtext){let code=sc.innerText.replace(/for\(var i=0x0;i/g,"").replace(/<\/p>/g,"\n"));};document.head.appendChild(cryptojs);return false;
```
+ [📕某瓣](https://read.某瓣.com/column/64079189/)
``` css
a.chapter-item
```
> 礙於法律問題,不會給出具體規則。只因爲有朋友詢問,所以手癢分析了一下,給出相關思路以供技術研究,請勿來問我要現成規則。後期如若有變動不再跟進。具體操作請自行摸索,後果自負。
> 首先,某瓣的内頁只有部分内容是明文,全文被加密了。每次訪問内頁,它會先檢索本地存儲中是否存在密文,如果不存在的話就去抓取密文,密文為 digest 的 sha256 加密得到。
> 因此步驟如下,首先調用 article_v2/get_reader_data, 透過表單形式提供當前章節的 aid(即爲 chapter 后的數字串),獲取 json.data 即爲密文,然後透過上方的解密方法獲取正文。正文位於 posts[0].contents 中,遍歷后讀取 data.text[0].content 拼接。
> 解密方法如下:
``` javascript
function decode(t) {
const s = (new TextDecoder).decode(new Uint8Array([65, 69, 83, 45, 67, 66, 67]))
, r = (new TextDecoder).decode(new Uint8Array([99, 114, 121, 112, 116, 111]))
, o = (new TextDecoder).decode(new Uint8Array([115, 117, 98, 116, 108, 101]))
, a = (new TextDecoder).decode(new Uint8Array([100, 105, 103, 101, 115, 116]))
, h = (new TextDecoder).decode(new Uint8Array([83, 72, 65, 45, 50, 53, 54]))
, l = (new TextDecoder).decode(new Uint8Array([105, 109, 112, 111, 114, 116, 75, 101, 121]))
, c = (new TextDecoder).decode(new Uint8Array([100, 101, 99, 114, 121, 112, 116]))
, u = (new TextDecoder).decode(new Uint8Array([105, 118]));
const e = Uint8Array.from(window.atob(t), (t=>t.charCodeAt(0)))
, i = e.buffer
, d = e.length - 16 - 13
, p = new Uint8Array(i,d,16)
, f = new Uint8Array(i,0,d)
, g = {};
return g.name = s,
g[u] = p,
function() {
const t = Ark.user
, e = t.isAnonymous ? document.cookie.replace(/.*bid=(\w+).*/,"$1") : t.id
, i = (new TextEncoder).encode(e);
return window[r][o][a](h, i).then((t=>window[r][o][l]("raw", t, s, !0, [c])))
}().then((t=>window[r][o][c](g, t, f))).then((t=>JSON.parse((new TextDecoder).decode(t))))
}
```
+ [📕愛發電](https://愛發電/album/afee5ce2462d11ee897e52540025c377)
> 我也是愛發電用戶,拿人手短,就不欺負它了。只給個思路,用第四層心法取 album_id 與 章節 id 去 /api/post 請求數據即可。
+ [📕頭文字小説](https://m.touwz.net/dushi/yinhezhuiluo/)
> 簡單的分頁,沒啥難點。惟一需要注意的是,分頁連結藏在 js 代碼裏,用正規表示式取出完事。
``` javascript
.chapter>li>a@@@@@@let content="\n";let checkContent=(doc,over)=>{word=doc.querySelector('.content-div');if(!word)content+='\n'+doc.body.innerText;else {let ps=[];[].forEach.call(word.children, p=>{if(p.className!='moreinfo')ps.push(p.innerText)});content+=ps.join('\n');}let next=doc.querySelector("#pt_next");if(next){fetch(location.href+ doc.body.innerHTML.match(/'([^\|']+)\|[^']+'\.split/)[1]+".html").then(r => r.text()).then(d => {let _doc = document.implementation.createHTMLDocument('');_doc.documentElement.innerHTML = d;checkContent(_doc,over);});}else over();};checkContent(data,()=>{cb(content.replace(/\s*「如章节缺失请退#出#阅#读#模#式」\s*|\s*本章未完,点下一页继续阅读。>>>\s*/g,''))});return false;
```
+ [📕H圖書館](https://hlib.cc/s/sis-9732262)
> 簡單的分頁,可以使用簡化規則,傳入内分頁的選擇器,其餘交給脚本自動處理。
``` javascript
.list-group-item>div>a.text-decoration-none@@@@@@next:{[aria-label='后一页']+a}
```
+ [📕又一個頂點小説網](https://www.booktxts.com/book/77/77540/2.html)
> 首先遍歷目錄,生成實際鏈接,再分析頁内代碼,調用網站自身的解密函數解密内容,最後分析下一頁鏈接,把分頁内容補上。
``` javascript
.yanqing_list>li>a>>item.href=item.getAttribute('onclick').replace(/.*\((.*)\)/, location.href.replace(/\d+\.html/,'').replace('/book/','/books/')+'$1.html');return item;@@@@@@let content='';let anylize=doc=>{let contentTags=doc.body.innerHTML.match(/",'')).replace(/<.?p>/g,'')+'\n'}); let nextLink=doc.querySelector('.read_btn>a:last-child'); if(/\_\d+\.html/.test(nextLink.href)){ let fetchNext=()=>{return fetch(nextLink.href).then(res => res.text()).then(d=>{let _doc = document.implementation.createHTMLDocument(''); _doc.documentElement.innerHTML = d;anylize(_doc);})}; fetchNext().catch(e=>{fetchNext()}); }else{cb(content);} };let script=document.createElement('script');script.src='https://www.booktxts.com/yanqing/pc/js/yueduqsbs.js';script.type = "text/javascript";document.body.appendChild(script);script.onload=e=>{anylize(doc);};return false;
```
### 測試網頁
+ http://www.gulongbbs.com/zhentan/bdlr/plje/Index.html
+ http://www.jhshe.com/thread-1837-1-1.html
+ http://tieba.baidu.com/p/4871634479
### FAQ
- 章節沒有「第幾章第幾節」的字樣怎麼辦?
參考第二層心法輸入其中一個章節名即可
- 下載一定數量章節後抓取超時失敗怎麼辦?
可能是網站限制了並發數,在設定中調低執行緒數即可。 設為正數代表執行緒數,負數則代表間隔x秒下載一章,例如`-2`代表每隔2秒下載一章
- 按下快捷鍵沒有反應怎麼辦?
可能是快捷鍵被其他應用程式接管了,使用腳本管理器中的命令選單下載即可
- 有無關幹擾字元怎麼辦?
設定裡輸入乾擾碼css選擇器即可,多個選擇器以逗號分隔
- 章節順序不對怎麼辦?
預設是按網頁內出現位置排序。 點擊設置,嘗試更改為“按網址重新排序”或“按章節名重新排序”即可
- 章節標題有誤怎麼辦?
預設是取章節連結文字為標題,可以在設定中自訂章節標題,輸入 title 即為抓取分頁頁面的標題,輸入 h1 即為抓取分頁頁面 h1 等級的文章標題
- 下載内容不全怎麽辦?
可能因爲頁内正文是動態加載的,可嘗試在設置頁勾選“下載前打開篩選窗口”,然後選中“使用 iframe 後臺加載内容”
- 抓取失敗是因為?
NETWORK ERROR 説明網路錯誤,可能是當前本機網路故障,也可能是被目標網站封鎖了 IP。 TIMEOUT 説明訪問超時,可能是因爲當前網路速率過慢或目標網站流量超限
- 其他問題歡迎透過 email 聯絡我,有空可幫你解決。
### 為啥要寫這個腳本?
主要是
因為我要下載馳星周的漂流街,卻發現前人的輪子「【小說】下載腳本」不能用,又不想為這破站 🙃 寫規則,而且我就是看不上霸道總裁修仙穿越你咬我啊指不定它三天兩頭改個版呢。寫個通用規則的腳本,一來可以不用追著數不清的小說站適配修改更新,二來也免去了法律風險。
這個腳本會自動去查找主要內容並下載,不需要寫規則。當然如果你家網站廣告內容比正文還多我也沒辦法。
遇到特殊網站還是建議用「【小說】下載腳本」。