嗨嘍已卸,大家好呀~這里是愛看美女的茜茜吶
環(huán)境使用:
Python 3.10 解釋器
Pycharm 編輯器
模塊使用
import requests --> 數(shù)據(jù)請求模塊 第三方模塊, 需要安裝
import re --> 正則表達(dá)式模塊 內(nèi)置模塊, 不需要安裝
import parsel --> 數(shù)據(jù)解析模塊 第三方模塊, 需要安裝
import os --> 文件操作模塊 內(nèi)置模塊, 不需要安裝
import concurrent.futures --> 線程池
如何安裝python第三方模塊:
win + R 輸入 cmd 點(diǎn)擊確定, 輸入安裝命令 pip install 模塊名 (pip install requests) 回車
在pycharm中點(diǎn)擊Terminal(終端) 輸入安裝命令
爬蟲基本實(shí)現(xiàn)思路
一. 數(shù)據(jù)來源分析
-
明確需求:
-
采集的網(wǎng)站是什么?
-
采集的數(shù)據(jù)是什么?
標(biāo)題/內(nèi)容
-
-
分析 標(biāo)題/內(nèi)容 是從哪里來的
通過瀏覽器自帶工具: 開發(fā)者工具抓包分析
打開開發(fā)者工具: F12 / 鼠標(biāo)右鍵點(diǎn)擊檢查選擇network
刷新網(wǎng)頁
-
搜索數(shù)據(jù), 找到數(shù)據(jù)包
二. 代碼實(shí)現(xiàn)步驟:
-
發(fā)送請求, 模擬瀏覽器對于url地址發(fā)送請求
-
獲取數(shù)據(jù), 獲取服務(wù)器返回響應(yīng)數(shù)據(jù)內(nèi)容
開發(fā)者工具: response
-
解析數(shù)據(jù), 提取我們想要的數(shù)據(jù)內(nèi)容
標(biāo)題/內(nèi)容
保存數(shù)據(jù), 把數(shù)據(jù)保存本地文件
單章小說下載
導(dǎo)入模塊
import requests
import re
import parsel
"""
-
發(fā)送請求, 模擬瀏覽器對于url地址發(fā)送請求
請求鏈接: https://www.biqudu.net/1_1631/3047505.html
安裝模塊方法:
win + R 輸入cmd, 輸入安裝命令 pip install requests
在pycharm終端, 輸入安裝命令
模擬瀏覽器 headers 請求頭:
字典數(shù)據(jù)結(jié)構(gòu)
AttributeError: 'set' object has no attribute 'items'
因?yàn)閔eaders不是字典數(shù)據(jù)類型, 而是set集合
"""
請求鏈接
url = 'https://www.biqudu.net/1_1631/3047505.html'
模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
發(fā)送請求
response = requests.get(url=url, headers=headers)
<Response [200]> 響應(yīng)對象, 表示請求成功
print(response)
"""
-
獲取數(shù)據(jù), 獲取服務(wù)器返回響應(yīng)數(shù)據(jù)內(nèi)容
開發(fā)者工具: response
response.text --> 獲取響應(yīng)文本數(shù)據(jù) <網(wǎng)頁源代碼/html字符串?dāng)?shù)據(jù)>
-
解析數(shù)據(jù), 提取我們想要的數(shù)據(jù)內(nèi)容
標(biāo)題/內(nèi)容
"""
獲取下來response.text <html字符串?dāng)?shù)據(jù)>, 轉(zhuǎn)成可解析對象
selector = parsel.Selector(response.text)
# 提取標(biāo)題
title = selector.xpath('//*[@class="bookname"]/h1/text()').get()
# 提取內(nèi)容
content = '\n'.join(selector.xpath('//*[@id="content"]/text()').getall())
print(title)
print(content)
"""
- 保存數(shù)據(jù), 把數(shù)據(jù)保存本地文件
"""
title <文件名> '.txt' 文件格式 a 追加保存 encoding 編碼格式 as 重命名
with open(title + '.txt', mode='a', encoding='utf-8') as f:
"""
第一章 標(biāo)題
小說內(nèi)容
第二章 標(biāo)題
小說內(nèi)容
"""
寫入內(nèi)容
f.write(title)
f.write('\n')
f.write(content)
f.write('\n')
小知識點(diǎn)
-
re正則表達(dá)式: 是直接對于字符串?dāng)?shù)據(jù)進(jìn)行解析
re.findall('什么數(shù)據(jù)', '什么地方') --> 從什么地方, 去找什么數(shù)據(jù)
.*? --> 可以匹配任意數(shù)據(jù), 除了\n換行符
# 提取標(biāo)題 title = re.findall('<h1>(.*?)</h1>', response.text)[0] # 提取內(nèi)容 content = re.findall('<div id="content">(.*?)<p>', response.text, re.S)[0].replace('<br/><br/>', '\n')
-
css選擇器: 根據(jù)標(biāo)簽屬性提取數(shù)據(jù)
.bookname h1::text
類名為bookname下面h1標(biāo)簽里面文本
get() --> 提取第一個標(biāo)簽數(shù)據(jù)內(nèi)容 返回字符串
getall() --> 提取多個數(shù)據(jù), 返回列表
# 提取標(biāo)題 title = selector.css('.bookname h1::text').get() # 提取內(nèi)容 content = '\n'.join(selector.css('#content::text').getall())
xpath節(jié)點(diǎn)提取: 提取標(biāo)簽節(jié)點(diǎn)提取數(shù)據(jù)
整本小說下載
import requests
import re
import parsel
import os
# 請求鏈接: 小說目錄頁
list_url = 'https://www.biqudu.net/1_1631/'
# 模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 發(fā)送請求
html_data = requests.get(url=list_url, headers=headers).text
# 提取小說名字
name = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 自動創(chuàng)建一個文件夾
file = f'{name}\\'
if not os.path.exists(file):
os.mkdir(file)
# 提取章節(jié)url
url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
# for循環(huán)遍歷
for url in url_list:
index_url = 'https://www.biqudu.net' + url
print(index_url)
# # 請求鏈接
# url = 'https://www.biqudu.net/1_1631/3047506.html'
# 模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 發(fā)送請求
response = requests.get(url=index_url, headers=headers)
# <Response [200]> 響應(yīng)對象, 表示請求成功
print(response)
# 獲取下來response.text <html字符串?dāng)?shù)據(jù)>, 轉(zhuǎn)成可解析對象
selector = parsel.Selector(response.text)
# 提取標(biāo)題
title = selector.xpath('//*[@class="bookname"]/h1/text()').get()
# 提取內(nèi)容
content = '\n'.join(selector.xpath('//*[@id="content"]/text()').getall())
print(title)
# print(content)
# title <文件名> '.txt' 文件格式 a 追加保存 encoding 編碼格式 as 重命名
with open(file + title + '.txt', mode='a', encoding='utf-8') as f:
f.write(title)
f.write('\n')
f.write(content)
f.write('\n')
多線程采集小說
導(dǎo)入模塊
import requests
import re
import parsel
import os
import concurrent.futures
def get_response(html_url):
"""
發(fā)送請求函數(shù)
:param html_url: 請求鏈接
:return: response響應(yīng)對象
"""
# 模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
return response
def get_list_url(html_url):
"""
獲取章節(jié)url/小說名
:param html_url: 小說目錄頁
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取小說名字
name = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取章節(jié)url
url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
return name, url_list
def get_content(html_url):
"""
獲取小說內(nèi)容/小說標(biāo)題
:param html_url: 小說章節(jié)url
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取標(biāo)題
title = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取內(nèi)容
content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
return title, content
def save(name, title, content):
"""
保存數(shù)據(jù)函數(shù)
:param name: 小說名
:param title: 章節(jié)名
:param content: 內(nèi)容
:return:
"""
# 自動創(chuàng)建一個文件夾
file = f'{name}\\'
if not os.path.exists(file):
os.mkdir(file)
with open(file + title + '.txt', mode='a', encoding='utf-8') as f:
"""
第一章 標(biāo)題
小說內(nèi)容
第二章 標(biāo)題
小說內(nèi)容
"""
# 寫入內(nèi)容
f.write(title)
f.write('\n')
f.write(content)
f.write('\n')
print(title, '已經(jīng)保存')
def main(home_url):
# index_url = 'https://www.biqudu.net' + url
title, content = get_content(html_url=home_url)
save(name, title, content)
if __name__ == '__main__':
url = 'https://www.biqudu.net/1_1631/'
name, url_list = get_list_url(html_url=url)
exe = concurrent.futures.ThreadPoolExecutor(max_workers=7)
for url in url_list:
index_url = 'https://www.biqudu.net' + url
exe.submit(main, index_url)
exe.shutdown()
下載排行所有小說
import requests
import re
import parsel
import os
def get_response(html_url):
"""
發(fā)送請求函數(shù)
:param html_url: 請求鏈接
:return: response響應(yīng)對象
"""
# 模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
return response
def get_list_url(html_url):
"""
獲取章節(jié)url/小說名
:param html_url: 小說目錄頁
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取小說名字
name = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取章節(jié)url
url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
return name, url_list
def get_content(html_url):
"""
獲取小說內(nèi)容/小說標(biāo)題
:param html_url: 小說章節(jié)url
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取標(biāo)題
title = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取內(nèi)容
content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
return title, content
def save(name, title, content):
"""
保存數(shù)據(jù)函數(shù)
:param name: 小說名
:param title: 章節(jié)名
:param content: 內(nèi)容
:return:
"""
# 自動創(chuàng)建一個文件夾
file = f'{name}\\'
if not os.path.exists(file):
os.mkdir(file)
with open(file + title + '.txt', mode='a', encoding='utf-8') as f:
"""
第一章 標(biāo)題
小說內(nèi)容
第二章 標(biāo)題
小說內(nèi)容
"""
# 寫入內(nèi)容
f.write(title)
f.write('\n')
f.write(content)
f.write('\n')
print(title, '已經(jīng)保存')
def get_novel_id(html_url):
"""
獲取小說ID
:param html_url: 某分類的鏈接
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
novel_data = get_response(html_url=html_url).text
selector = parsel.Selector(novel_data)
href = selector.css('.l .s2 a::attr(href)').getall()
href = [i.replace('/', '') for i in href]
return href
def main(home_url):
href = get_novel_id(html_url=home_url)
for novel_id in href:
novel_url = f'https://www.biqudu.net/{novel_id}/'
name, url_list = get_list_url(html_url=novel_url)
print(name, url_list)
for url in url_list:
index_url = 'https://www.biqudu.net' + url
title, content = get_content(html_url=index_url)
save(name, title, content)
break
if __name__ == '__main__':
html_url = 'https://www.biqudu.net/biquge_1/'
main(html_url)
小說搜搜功能
# 導(dǎo)入數(shù)據(jù)請求模塊 --> 第三方模塊, 需要安裝
import requests
# 導(dǎo)入正則表達(dá)式模塊 --> 內(nèi)置模塊, 不需要安裝
import re
# 導(dǎo)入數(shù)據(jù)解析模塊 --> 第三方模塊, 需要安裝
import parsel
# 導(dǎo)入文件操作模塊 --> 內(nèi)置模塊, 不需要安裝
import os
# 導(dǎo)入漂亮的表格
import prettytable as pt
def get_response(html_url):
"""
發(fā)送請求函數(shù)
:param html_url: 請求鏈接
:return: response響應(yīng)對象
"""
# 模擬瀏覽器 headers 請求頭
headers = {
# user-agent 用戶代理 表示瀏覽器基本身份信息
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
return response
def get_list_url(html_url):
"""
獲取章節(jié)url/小說名
:param html_url: 小說目錄頁
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取小說名字
name = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取章節(jié)url
url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
return name, url_list
def get_content(html_url):
"""
獲取小說內(nèi)容/小說標(biāo)題
:param html_url: 小說章節(jié)url
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
html_data = get_response(html_url).text
# 提取標(biāo)題
title = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 提取內(nèi)容
content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
return title, content
def save(name, title, content):
"""
保存數(shù)據(jù)函數(shù)
:param name: 小說名
:param title: 章節(jié)名
:param content: 內(nèi)容
:return:
"""
# 自動創(chuàng)建一個文件夾
file = f'{name}\\'
if not os.path.exists(file):
os.mkdir(file)
with open(file + name + '.txt', mode='a', encoding='utf-8') as f:
"""
第一章 標(biāo)題
小說內(nèi)容
第二章 標(biāo)題
小說內(nèi)容
"""
# 寫入內(nèi)容
f.write(title)
f.write('\n')
f.write(content)
f.write('\n')
print(title, '已經(jīng)保存')
def get_novel_id(html_url):
"""
獲取小說ID
:param html_url: 某分類的鏈接
:return:
"""
# 調(diào)用發(fā)送請求函數(shù)
novel_data = get_response(html_url=html_url).text
selector = parsel.Selector(novel_data)
href = selector.css('.l .s2 a::attr(href)').getall()
href = [i.replace('/', '') for i in href]
return href
def search(word):
"""
搜索功能
:param word: 書名/作者
:return:
"""
search_url = f'https://www.biqudu.net/searchbook.php?keyword={word}'
# 發(fā)送請求
search_data = get_response(html_url=search_url).text
# 解析數(shù)據(jù), 提取小說名字/作者/小說ID
selector = parsel.Selector(search_data)
lis = selector.css('.novelslist2 li')
novel_info = []
tb = pt.PrettyTable()
tb.field_names = ['序號', '書名', '作者', '書ID']
num = 0
for li in lis[1:]:
# 小說名字
name = li.css('.s2 a::text').get()
novel_id = li.css('.s2 a::attr(href)').get().replace('/', '')
writer = li.css('.s4::text').get()
dit = {
'name': name,
'writer': writer,
'novel_id': novel_id,
}
tb.add_row([num, name, writer, novel_id])
num += 1
novel_info.append(dit)
print('你搜索的結(jié)果如下:')
print(tb)
novel_num = input('請輸入你想要下載的小說序號: ')
novel_id = novel_info[int(novel_num)]['novel_id']
return novel_id
def main(word):
"""
主函數(shù)
"""
novel_id = search(word)
novel_url = f'https://www.biqudu.net/{novel_id}/'
name, url_list = get_list_url(html_url=novel_url)
print(name, url_list)
for url in url_list:
index_url = 'https://www.biqudu.net' + url
title, content = get_content(html_url=index_url)
save(name, title, content)
if __name__ == '__main__':
word = input('請輸入你搜索小說名: ')
main(word)
制作GUI界面
導(dǎo)入模塊
import tkinter as tk
from tkinter import ttk
def show():
name = name_va.get()
print('輸入的名字是:', name)
def download():
name = num_va.get()
print('輸入的序號:', name)
創(chuàng)建界面
root = tk.Tk()
設(shè)置標(biāo)題
root.title('小說下載器')
設(shè)置界面大小
root.geometry('500x500+200+200')
設(shè)置可變變量
name_va = tk.StringVar()
設(shè)置標(biāo)簽
search_frame = tk.Frame(root)
search_frame.pack(pady=10)
設(shè)置文本
tk.Label(search_frame, text='書名 作者', font=('微軟雅黑', 15)).pack(side=tk.LEFT, padx=10)
設(shè)置輸入框
tk.Entry(search_frame, relief='flat', textvariable=name_va).pack(side=tk.LEFT)
序號獲取
num_va = tk.StringVar()
查詢下載輸入框
download_frame = tk.Frame(root)
download_frame.pack(pady=10)
設(shè)置文本
tk.Label(download_frame, text='小說 序號', font=('微軟雅黑', 15)).pack(side=tk.LEFT, padx=10)
設(shè)置輸入框
tk.Entry(download_frame, relief='flat', textvariable=num_va).pack(side=tk.LEFT)
按鈕設(shè)置
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
設(shè)置查詢按鈕
tk.Button(button_frame, text='查詢', font=('微軟雅黑', 10), relief='flat', bg='#88e2d6', width=10, command=show).pack(side=tk.LEFT, padx=10)
設(shè)置下載按鈕
tk.Button(button_frame, text='下載', font=('微軟雅黑', 10), relief='flat', bg='#88e2d6', width=10, command=download).pack(side=tk.LEFT, padx=10)
提前設(shè)置標(biāo)簽名字和中文顯示內(nèi)容
columns = ('num', 'writer', 'name', 'novel_id')
columns_value = ('序號', '作者', '書名', '書ID')
tree_view = ttk.Treeview(root, height=18, show='headings', columns=columns)
設(shè)置列名
tree_view.column('num', width=40, anchor='center')
tree_view.column('writer', width=40, anchor='center')
tree_view.column('name', width=40, anchor='center')
tree_view.column('novel_id', width=40, anchor='center')
給列名設(shè)置顯示的名字
tree_view.heading('num', text='序號')
tree_view.heading('writer', text='作者')
tree_view.heading('name', text='書名')
tree_view.heading('novel_id', text='書ID')
tree_view.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
展示界面
root.mainloop()
尾語
感謝你觀看我的文章吶~本次航班到這里就結(jié)束啦 ??
希望本篇文章有對你帶來幫助 ??佛玄,有學(xué)習(xí)到一點(diǎn)知識~
躲起來的星星??也在努力發(fā)光,你也要努力加油(讓我們一起努力叭)累澡。