Python搜索書名獲取整本資源_筆趣閣

来源:https://www.cnblogs.com/H-J-Jay/archive/2022/05/29/Python_ByHuMou_05_29.html
-Advertisement-
Play Games

前言 偶然一天把某項目文檔傳到手機上,用手機自帶的閱讀器方便隨時拿出來查閱。看著我那好久沒點開的閱讀器,再看著書架上擺著幾本不知道是多久之前導入的小說。 閉上眼,我仿佛看到那時候的自己。側躺著縮在被窩裡,亮度調到最低,看的津津有味。 睜開眼,一聲短嘆,心中五味雜陳,時間像箭一樣飛逝而去,過去靜止不動 ...


前言

偶然一天把某項目文檔傳到手機上,用手機自帶的閱讀器方便隨時拿出來查閱。看著我那好久沒點開的閱讀器,再看著書架上擺著幾本不知道是多久之前導入的小說。

閉上眼,我仿佛看到那時候的自己。側躺著縮在被窩裡,亮度調到最低,看的津津有味。

睜開眼,一聲短嘆,心中五味雜陳,時間像箭一樣飛逝而去,過去靜止不動,未來姍姍來遲。

正好最近又重溫了下python,準備做一個簡單的獲取小說txt文件的程式。

 

一、前期準備

1.安裝第三方庫

win + r 輸入cmd

命令行輸入

pip install requests

pip install pyquery

嫌麻煩pycharm直接搜索包安裝就行

2.感謝---支持

純屬愛好,僅供學習

 

 


 

 

二、主要步驟

1.請求網頁

老樣子,F12進控制台,輸入 document.chartset 查看網頁編碼


代碼如下:

1 # 請求網頁 獲取網頁數據
2 def GetHTMLText(url: str) -> str:
3     res = requests.get(url=url, headers=GetHeader(), proxies=GetProxy())   
4     res.encoding = "GBK"
5     html: str = res.text
6     return html

 

 

2.獲取章節目錄

測試地址:---

Ctrl + Shift + C ,選擇章節目錄任意一章

可以發現章節目錄class="zjlist"下的<dd>標簽內含有每一章節的信息,該章節的url和章節名

 

 

代碼如下:

1 # 獲取章節目錄
2 def GetPageTree(doc: pQ) -> pQ:
3     pageTree: pQ = doc('.zjlist dd a')
4     return pageTree

 

 3.輸入轉碼

GBK轉碼:aTool線上工具

在搜索框內輸入名稱,searchkey=,後就是該名稱對應的GBK編碼

將鏈接後的編碼輸進進行解碼,得到你所輸入的文字內容

 

 

代碼如下:

1 # 輸入轉碼 獲取搜索到的書籍鏈接
2 def GetSearchUrl(Novel_Name: str) -> str:
3     StrToGbk: bytes = Novel_Name.encode("gbk")
4     GbkToStr: str = str(StrToGbk)
5     Url_input = GbkToStr[2:-1].replace("\\x", "%").upper()
6     Url = "---" + "searchtype=articlename&searchkey="
7     return Url + Url_input

 

 

4.抓取模式

搜索到小說之後跳轉到搜索到的網頁,可能會出現兩種情況

一種是一次搜索到結果

還有一種是搜索到多種結果,需要對這個網頁再做一次解析篩選

判斷網頁容器的id="info",是否有這個節點


 

代碼如下:

1 # 抓取模式
2 def GetModel(doc: pQ) -> bool:
3     if doc('#info'):
4         return True  # 一次搜索到,不需要篩選
5     else:
6         return False

 

 


 

 

 

三、代碼展示

  1 import os
  2 import requests
  3 import time
  4 import re
  5 from random import choice
  6 from pyquery import PyQuery as pQ
  7 
  8 
  9 # 獲取請求頭
 10 def GetHeader() -> dict:
 11     header = [  # 請求頭
 12         {
 13             "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36"
 14         },
 15         {
 16             "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
 17         },
 18         {
 19             "User-Agent": "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"
 20         },
 21         {
 22             "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36"
 23         },
 24         {
 25             "User-Agent": "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
 26         },
 27         {
 28             "User-Agent": "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
 29         },
 30         {
 31             "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36"
 32         },
 33         {
 34             "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36"
 35         },
 36         {
 37             "User-Agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)"
 38         },
 39         {
 40             "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
 41         }
 42     ]
 43     return choice(header)
 44 
 45 
 46 # 獲取代理
 47 def GetProxy() -> dict:
 48     proxies = [  # 代理
 49         {
 50             "Https": "60.170.204.30:8060"
 51         },
 52         {
 53             "Https": "103.37.141.69:80"
 54         },
 55         {
 56             "Https": "183.236.232.160:8080"
 57         },
 58         {
 59             "Https": "202.55.5.209:8090"
 60         },
 61         {
 62             "Https": "202.55.5.209:8090"
 63         }
 64     ]
 65     return choice(proxies)
 66 
 67 
 68 # 輸入轉碼 獲取搜索到的書籍鏈接
 69 def GetSearchUrl(Novel_Name: str) -> str:
 70     StrToGbk: bytes = Novel_Name.encode("gbk")
 71     GbkToStr: str = str(StrToGbk)
 72     Url_input = GbkToStr[2:-1].replace("\\x", "%").upper()
 73     Url = "---" + "modules/article/search.php?searchtype=articlename&searchkey="
 74     return Url + Url_input
 75 
 76 
 77 # 請求網頁 獲取網頁數據
 78 def GetHTMLText(url: str) -> str:
 79     res = requests.get(url=url, headers=GetHeader(), proxies=GetProxy())
 80     # Console --- document.charset ---'GBK'
 81     res.encoding = "GBK"
 82     html: str = res.text
 83     return html
 84 
 85 
 86 # 獲取網頁解析
 87 def GetParse(url: str) -> pQ:
 88     text = GetHTMLText(url)
 89     doc: pQ = pQ(text)
 90     return doc
 91 
 92 
 93 # 獲取小說名
 94 def GetNovelName(doc: pQ) -> str:
 95     con = doc('#info')
 96     novel_name: str = con('h1').text().split(' ')[0]
 97     return novel_name
 98 
 99 
100 # 獲取章節目錄
101 def GetPageTree(doc: pQ) -> pQ:
102     pageTree: pQ = doc('.zjlist dd a')
103     return pageTree
104 
105 
106 # 提取章節鏈接跳轉後的頁面內容 id="content"
107 def GetNovel(url) -> str:
108     doc = GetParse(url)
109     con = doc('#content')
110     novel: str = con.text()
111     return novel
112 
113 
114 # 獲取總頁數
115 def GetPageNums(doc: pQ):
116     pageNums = doc('.form-control option')
117     return pageNums
118 
119 
120 # 獲取novel主頁鏈接
121 def GetHomeUrl(doc: pQ) -> str:
122     PageNums = GetPageNums(doc)
123     for page in PageNums.items():
124         if page.text() == "第1頁":
125             return page.attr('value')
126 
127 
128 # 抓取模式
129 def GetModel(doc: pQ) -> bool:
130     if doc('#info'):
131         return True  # 一次搜索到,不需要篩選
132     else:
133         return False
134 
135 
136 # 搜索到結果開始抓取
137 # Args_url---novel主頁鏈接
138 # ms---間隔時間,單位:ms
139 # url_ 主網站
140 def GetDate_1(Args_url: str, doc: pQ, ms: int, url_: str = "---") -> None:
141     NovelName = GetNovelName(doc)
142     PageNums = GetPageNums(doc)
143     file_path = os.getcwd() + "\\" + NovelName  # 文件存儲路徑
144     setDir(file_path)  # 判斷路徑是否存在,不存在創建,存在刪除
145     Seconds: float = ms / 1000.0
146     for page in PageNums.items():
147         url = url_ + page.attr('value')  # 每一頁的鏈接
148         currentPage = page.text()  # 當前頁
149         doc: pQ = GetParse(url)
150         page_tree = GetPageTree(doc)
151         for page_Current in page_tree.items():
152             page_name: str = page_Current.text()  # 章節名
153             page_link = page_Current.attr('href')  # 章節鏈接
154             novel = page_name + "\n\n" + GetNovel(Args_url + page_link) + "\n\n"  # 文章內容
155             page_Name = clean_file_name(page_name)  # 處理後的章節名
156             download_path = file_path + "\\" + NovelName + ".txt"  # 文件下載路徑
157             with open(download_path, "a", encoding="utf-8") as f:
158                 f.write(novel)
159                 print("正在下載 {}...".format(page_Name))
160                 time.sleep(Seconds)
161                 f.close()
162             print("{}下載成功\n".format(page_Name))
163         print("{}下載完成\n".format(currentPage))
164     print("{}下載完成!".format(NovelName))
165 
166 
167 # 搜索到重覆結果,需要進行篩選.匹配成功返迴首頁的網址
168 def GetUrl_2(doc: pQ, SearchName: str) -> str:
169     con = doc('.odd a').items()
170     for Title in con:
171         if Title.text() == SearchName:
172             url: str = Title.attr('href')
173             return url
174 
175 
176 # 文件處理
177 def setDir(filepath):
178     if not os.path.exists(filepath):  # 如果文件夾不存在就創建
179         os.mkdir(filepath)
180     else:
181         for i in os.listdir(filepath):  # os.listdir(filepath)返回一個列表,裡面是當前目錄下麵的所有東西的相對路徑
182             file_data = filepath + "\\" + i  # 當前文件夾下文件的絕對路徑
183             if os.path.isfile(file_data):
184                 os.remove(file_data)  # 文件存在-刪除
185 
186 
187 # 異常文件名處理
188 def clean_file_name(filename: str):
189     invalid_chars = '[\\\/:*??"<>|]'
190     replace_char = '-'
191     return re.sub(invalid_chars, replace_char, filename)
192 
193 
194 # 保存文件
195 def SaveFile(url: str, searchName: str):
196     doc = GetParse(url)
197     url_: str = "---" #懂得都懂
198     try:
199         if GetModel(doc):
200             url = url_ + GetHomeUrl(doc)
201             doc = doc
202         else:
203             url = GetUrl_2(doc, searchName)
204             doc = GetParse(url)
205         GetDate_1(Args_url=url, doc=doc, ms=100)
206     except Exception as result:
207         print("{}".format(result))
208     finally:
209         print("請輸入有效書名")
210 
211 
212 # 輸入名字搜索
213 def main():
214     SearchName = input("請輸入需要下載的書名:")
215     url = GetSearchUrl(SearchName)
216     SaveFile(url, SearchName)
217 
218 
219 if __name__ == "__main__":
220     main()
View Code

 

 


 

 

 

四、運行效果

 

 

 

 

 


 

 

 

總結

按名稱搜索跟直接拿首頁鏈接原理差不多,只不過多了個篩選的操作

以上就是今天要分享的內容,時間原因還有很多可以優化的地方,後面有時間再改吧……

最後說說自己的一些想法,為什麼現在對小說沒什麼感覺了。

看小說除了讓我的鼻梁上戴著的東西越來越厚之外,還讓我的作息變得一團糟。我是個管不住自己的人,以前看小說最著迷的時候,除了吃飯睡覺,剩下時間全拿來看小說了。

當然,看小說也並不像我說的那樣百害無一利,但是要註意合理安排好自己的時間,勞逸結合。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 緊急更新第二彈,然後就剩下最後一彈,也就是整個前臺的項目 一.購物車 1.加入購物車(新知識點) 加入到購物車是需要介面操作的,因為我們需要將用戶的加入到購物車的保存到伺服器資料庫,你的賬號後面才會在你自己的購物車看到,所以這裡要先寫介面 然後vuex三部曲, 返回來的數據沒有data,就是告訴你成 ...
  • jQuery jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝Java ...
  • 這幾天一直都在做項目,只是沒有上傳上來,即將把前臺項目完結了。現在開始更新整個前臺的部分 一.麵包屑處理 1.分類操作 點擊三級聯動進入搜索產生麵包屑,直接取參數中的name即可 點擊x怎麼幹掉這個麵包屑,直接讓其v-if為這個name,如果點擊x就把name清空 清空還沒完,清空應該再發一次請求, ...
  • 本章是系列文章的第五章,介紹了指針分析方法。指針分析在C/C++語言中非常重要,分析的結果可以有效提升指針的優化效率。 本文中的所有內容來自學習DCC888的學習筆記或者自己理解的整理,如需轉載請註明出處。周榮華@燧原科技 5.1 概念 指針是許多重要編程語言的特性之一 指針的使用,可以避免大量的數 ...
  • 第四章: 設計與聲明 ###18. 讓介面更容易被正確使用,不易被誤用 將你的class的public介面設計的符合class所扮演的角色,必要時不僅對傳參類型限制,還對傳參的值域進一步限制。 ###19. 設計class猶如設計type 內置類型如int、float等,本質也是一個class,用戶 ...
  • 前言 還記得你第一次遇到「線程安全」這個詞的時候嗎? 我第一次遇到線程安全這個詞是在學習多線程併發操作的時候,看到人家文章里出現這個詞,還有說各種線程安全的類,但是一開始並不理解線程安全是什麼意思,也沒去深究線程怎樣是安全的?怎樣是不安全的?只是腦子裡接收了這麼一個詞。 線程安全是多線程編程時的計算 ...
  • JVM 是Java的基石,Java從業者需要瞭解。JVM不是一個新的知識,網上文章很多,本篇的不同之處在於參考一手資料、內容經過反覆推敲。本文將會有篩選地研究JVM的精華部分,至少達到準系統架構師夠用的程度。本篇主要分享學習Java Class文件以及類載入器CLassLoader的知識。 ...
  • 資料庫表之間關係: 一對一 (可以看做一對多的特例) 一對多 多對多 下圖將涵蓋了所有關係。 根據restful介面風格,我們最終會落到一個實體上,示例按照b表。其他表同理。 GET https://ip:port/xx/xx/1/0/b 查詢的場景: 只需要b表的某些元素 需要b某些元素,及相關聯 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...