Python多进程模块实战: 下载某小说网小说内容
练习一下Python的multiprocessing模块,成品代码如下:
#!/usr/bin/python3
# 书站爬虫
# 仅限学习多进程机制使用 使用后果全部由使用者自行承担.
import requests
import parsel
from tqdm import tqdm
from time import sleep
import os
from multiprocessing import Process, Value
# 多进程中共享的变量
# 使用multiprocessing自带的Value
q = Value('d', 0) #进程数
status = Value('d', 0) #运行锁
def new_sub_thread(func, args=()):
# 多进程,启动!
thread = Process(target=func, args=args, daemon=True)
thread.start()
def get_response(html_url, text_mode):
headers = {
'User-Agent': 'Wget/1.21.1',
'accept-language': 'zh-CN,zh'
}
try:
response = requests.get(url=html_url, headers=headers)
except:
# 失败重试(小的网络波动)
sleep(2)
try:
response = requests.get(url=html_url, headers=headers)
except:
# 第二次重试(书站特有dns污染)
sleep(4)
response = requests.get(url=html_url, headers=headers)
if text_mode == True:
# 书站特有编码问题 标题和正文的编码不一样...
response.encoding = response.apparent_encoding
return response
def save(novel_name, title, content):
# 原始的保存机制...
filename = f'{novel_name}' + '.txt'
with open(filename, mode='w', encoding='utf-8') as f:
# 写入标题
f.write(title)
# 换行
f.write('\n')
# 写入小说内容
f.write(content)
# 换行
f.write('\n')
def get_one_novel(name, novel_url, q, k, fulllen, status):
# 下载某一章节的内容
#name: 小说名/ID, novel_url: 单章url, q: (共享)当前进程数, k: 下载章数, status: (共享)状态 0/1
q.value=q.value+1 #进程数+1
# 调用请求网页数据函数
response = get_response(novel_url, True)
# 转行成selector解析对象
selector = parsel.Selector(response.text)
# 获取小说标题
title = selector.css('.bookname h1::text').get()
# 获取小说内容 返回的是list
content_list = selector.css('#content::text').getall()
# '\n'.join(列表) 把列表转换成字符串 并且带上换行
content_str = '\n'.join(content_list)
save(name+'_tmp/'+str(k)+'_'+name, title, content_str)
q.value=q.value-1 #进程数-1
if k == fulllen:
status.value=1 #解运行锁
def get_all_url(html_url, novel_id, isreplace):
# 调用请求网页数据函数
response = get_response(html_url, False)
# 转行成selector解析对象
selector = parsel.Selector(response.text)
# 所有的url地址都在 a 标签里面的 href 属性中
dds = selector.css('#list dd a::attr(href)').getall()
# 小说名字 同时检测小说是否存在
try:
novel_name = selector.css('meta[property="og:title"]::attr(content)').get()
except:
print("这本小说不存在...请检查ID是否正确")
raise SystemExit() #手动退出
print("ID: "+str(novel_id)+" 标题: "+novel_name+" 章数: "+str(len(dds)))
k = 1 #从1开算
if isreplace == 1:
novel_id = novel_name
os.system(f'mkdir {novel_id}_tmp') #缓存目录
for dd in tqdm(dds):
while q.value == 8:
# max 八进程 多了会等待结束一个进程后再继续
sleep(0.2)
fulllen = len(dds)
novel_url = base_url + dd
new_sub_thread(get_one_novel, (novel_id, novel_url, q, k, fulllen, status))
sleep(0.2)
k = k+1
while status.value == 0:
sleep(1) #死循环直到跑完
while q.value != 0:
sleep(0.5) #等待跑完
file1 = open(f'{novel_id}.txt', 'w')
for i in range(1, len(dds)+1):
f = open(f'{novel_id}_tmp/{i}_{novel_id}.txt')
file1.write(f.read())
f.close()
file1.close()
os.system(f'rm -r {novel_id}_tmp')
print("下载完成!")
def main():
novel_id = input('输入锡海小说网的ID: ')
global base_url
#base_url = input('输入主站Url(eg: https://www.otcwuxi.com): ')
base_url = 'https://www.otcwuxi.com'
print("主站Url已默认: https://www.otcwuxi.com")
url= base_url + '/chapter/' + novel_id + '/'
isreplace = 1 #是否将小说文件名改为小说名字
get_all_url(url, novel_id, isreplace)
if __name__ == '__main__':
main()
仅限学习多进程机制使用,使用后果由使用者自行承担。因特殊原因本文章不接受评论。
--------------
你已经看完这篇博文了!
本文来自博客园,作者:星如雨yu,转载请注明原文链接:https://www.cnblogs.com/tianpanyu/p/17689345.html
另,建议转载手动看一眼,把代码块转过去呗(超小声嘀咕)