您的位置:首页 > 娱乐 > 八卦 > 上海优质建筑设计网_网站的访问量怎么查_网页生成器_南昌seo专业团队

上海优质建筑设计网_网站的访问量怎么查_网页生成器_南昌seo专业团队

2025/3/8 20:27:34 来源:https://blog.csdn.net/weixin_64110589/article/details/144945564  浏览:    关键词:上海优质建筑设计网_网站的访问量怎么查_网页生成器_南昌seo专业团队
上海优质建筑设计网_网站的访问量怎么查_网页生成器_南昌seo专业团队

注意:

        该代码爬取小说不久或许会失效,有时候该网站会被封禁,代码只供参考,不同小说不同网址会有差异 

神印王座II皓月当空最新章节_神印王座II皓月当空全文免费阅读-笔趣阁

一、多线程爬虫

1.1、单线程爬虫的问题

        爬虫通常被认为是IO密集型的程序,因为它们主要依赖于网络请求来获取数据。然而,IO处理的速度相对较慢,可能导致爬虫的整体速度受限。具体来说,单线程爬虫在处理大量网页时效率较低,主要存在以下几个问题:

  1. 速度慢:单线程爬虫只能一个接一个地请求网页,缺乏并发能力。在面对大量网页时,这种逐个请求的方式显著增加了爬取所需的时间。

  2. 资源利用率低:在等待网络响应的过程中,CPU处于闲置状态,未能充分利用系统资源。这种低效利用不仅影响了爬虫的速度,也使得系统资源浪费。

  3. 易受限于网络延迟:网络延迟是影响爬虫效率的重要因素。单线程爬虫在面对高延迟的网络时,整体爬取时间会显著延长,从而降低用户体验。

1.2、原理

        多线程爬虫的核心原理是利用多线程并行处理多个网页请求,从而提高网络请求的并发性,加速数据抓取的过程。在这种架构中,爬虫将URL队列中的链接分配给多个线程进行处理,每个线程负责发送网络请求并获取响应。

具体来说,爬虫的工作流程如下:

  1. URL队列:爬虫首先维护一个包含待爬取URL的队列。每个线程从这个队列中取出一个URL进行处理。

  2. 并行请求:多个线程同时运行,独立地发送网络请求。在等待响应的过程中,线程不会闲置,而是可以继续处理队列中的其他URL。这种并行处理显著减少了整体的爬取时间。

  3. 结果队列:每个线程在获取到网页响应后,将结果存储到一个结果队列中。这个结构确保了数据的有序存储,并允许其他线程安全地读取这些结果。

  4. 数据写入:另一些线程则负责从结果队列中读取数据,并将其写入文件或进行进一步处理。这种分工使得爬虫的各个部分能够高效协作,最大限度地提高资源利用率。

1.3、主要组成部分

1.3.1、URL队列和结果队列

  • URL队列:存储待爬取的URL链接,通常使用线程安全的队列(如queue.Queue),以便多个线程可以安全地访问和修改。

  • 结果队列:用于存放从网页中提取的结果,允许在爬取完成后统一处理或存储。

from queue import Queue
urls_queue = Queue()
out_queue = Queue()

1.3.2、类包装

使用多个线程,不停的取URL队列中的url,并进行处理:

import threading
class ThreadCrawl(threading.Thread):def __init__(self, queue, out_queue):threading.Thread.__init__(self)self.queue = queueself.out_queue = out_queuedef run(self):while True:item = self.queue.get()

如果队列为空,线程就会被阻塞,直到队列不为空。

处理队列中的 一条数据后,就需要通知队列已经处理完该条数据 

1.3.3、函数包装

from threading import Thread
def func(args):pass
if __name__ == '__main__':info_html = Queue()t1 = Thread(target=func,args=(info_html,))

1.3.4、线程池

import threading  # 导入 threading 模块,用于创建和管理线程  
import time       # 导入 time 模块,使用 sleep 来模拟工作  
import queue      # 导入 queue 模块,使用线程安全的队列  class Threadingpool():  def __init__(self, max_num=10):  # 初始化线程池,最大线程数量为 max_num  self.queue = queue.Queue(max_num)  # 创建一个最大大小为 max_num 的队列  for i in range(max_num):  # 将线程类的引用放入队列中  self.queue.put(threading.Thread)  def getthreading(self):  # 从队列中获取一个线程  return self.queue.get()  def addthreading(self):  # 将新的线程类引用放回队列  self.queue.put(threading.Thread)  def func(p, i):  # 每个线程执行的函数  time.sleep(1)  # 通过休眠1秒来模拟工作  print(i)       # 打印传递给函数的索引  p.addthreading()  # 线程完成后,将线程返回到池中  if __name__ == "__main__":  p = Threadingpool()  # 创建一个 Threadingpool 实例  for i in range(20):  thread = p.getthreading()  # 从池中获取一个线程  t = thread(target=func, args=(p, i))  # 创建一个新线程,目标函数和参数  t.start()  # 启动线程

1.4、多线程函数爬虫

import re  # 导入正则表达式模块  
import requests  # 导入请求库,用于发送HTTP请求  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  
from threading import Thread  # 导入线程模块,用于实现多线程  
import time  # 导入时间模块,用于控制延时  def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  def get_new_url(url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取网页内容  resp = requests.get(url, header)  resp.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  titles = []  # 存储章节标题  new_urls = []  # 存储章节链接  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  # 获取章节标题并打印  print(e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0])  titles.append(e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0])  # 添加标题到列表  # 构造章节链接并添加到列表  new_urls.append('https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0])  return titles, new_urls  # 返回标题和链接列表  def spider(title, new_url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取章节内容  resp = requests.get(new_url, header)  resp.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  safe_title = sanitize_filename(title)  # 清理标题以作为文件名  print(title)  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for i in content:  f.write(i.strip() + "\n")  # 写入内容并清理空白  time.sleep(2)  # 每次抓取后暂停2秒,防止过于频繁的请求  if __name__ == '__main__':  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  titles, new_urls = get_new_url(url)  # 获取章节标题和链接  threads = []  # 存储线程列表  # 为每个章节创建一个线程进行抓取  for title, new_url in zip(titles, new_urls):  thread = Thread(target=spider, args=(title, new_url))  # 创建线程  threads.append(thread)  # 添加线程到列表  thread.start()  # 启动线程  # 等待所有线程完成  for thread in threads:  thread.join()  # 等待每个线程结束

1.5、多线程类爬虫

import re  # 导入正则表达式模块  
import requests  # 导入请求库,用于发送HTTP请求  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  
from threading import Thread  # 导入线程模块  
import time  # 导入时间模块,用于控制延时  class NovelSpider(Thread):  def __init__(self, title, new_url):  super().__init__()  # 调用父类的构造函数  self.title = title  # 章节标题  self.new_url = new_url  # 章节链接  self.headers = {'User-Agent': UserAgent().edge}  # 请求头  @staticmethod  def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  def run(self):  # 发送GET请求获取章节内容  resp = requests.get(self.new_url, headers=self.headers)  resp.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  safe_title = self.sanitize_filename(self.title)  # 清理标题以作为文件名  print(f"抓取中: {safe_title}")  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for i in content:  f.write(i.strip() + "\n")  # 写入内容并清理空白  time.sleep(2)  # 每次抓取后暂停2秒,防止过于频繁的请求  class NovelCrawler:  def __init__(self, base_url):  self.base_url = base_url  # 基础网址  self.headers = {'User-Agent': UserAgent().edge}  # 请求头  self.titles = []  # 存储章节标题  self.new_urls = []  # 存储章节链接  def get_new_url(self):  # 发送GET请求获取网页内容  resp = requests.get(self.base_url, headers=self.headers)  resp.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  title = e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0]  # 获取章节标题  print(title)  # 打印章节标题  self.titles.append(title)  # 添加标题到列表  new_url = 'https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0]  # 构造章节链接  self.new_urls.append(new_url)  # 添加链接到列表  def run(self):  self.get_new_url()  # 获取章节标题和链接  threads = []  # 存储线程列表  # 为每个章节创建一个线程进行抓取  for title, new_url in zip(self.titles, self.new_urls):  spider = NovelSpider(title, new_url)  # 创建爬虫实例  threads.append(spider)  # 添加线程到列表  spider.start()  # 启动线程  # 等待所有线程完成  for thread in threads:  thread.join()  # 等待每个线程结束  if __name__ == '__main__':  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  crawler = NovelCrawler(url)  # 创建爬虫控制器实例  crawler.run()  # 运行爬虫

1.6、 多线程--线程池

import re  # 导入正则表达式模块  
import requests  # 导入请求库,用于发送HTTP请求  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  
from concurrent.futures import ThreadPoolExecutor  # 导入线程池执行器  
import time  # 导入时间模块,用于控制延时  def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  def get_new_url(url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取网页内容  resp = requests.get(url, headers=header)  resp.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  titles = []  # 存储章节标题  new_urls = []  # 存储章节链接  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  # 获取章节标题并打印  title = e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0]  print(title)  # 打印章节标题  titles.append(title)  # 添加标题到列表  # 构造章节链接并添加到列表  new_urls.append('https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0])  return titles, new_urls  # 返回标题和链接列表  def spider(title, new_url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取章节内容  resp = requests.get(new_url, headers=header)  resp.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  safe_title = sanitize_filename(title)  # 清理标题以作为文件名  print(f"抓取中: {safe_title}")  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for i in content:  f.write(i.strip() + "\n")  # 写入内容并清理空白  time.sleep(2)  # 每次抓取后暂停2秒,防止过于频繁的请求  if __name__ == '__main__':  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  titles, new_urls = get_new_url(url)  # 获取章节标题和链接  # 使用线程池进行抓取  with ThreadPoolExecutor(max_workers=10) as executor:  # 设置最大工作线程数  # 为每个章节提交任务  for title, new_url in zip(titles, new_urls):  executor.submit(spider, title, new_url)  # 提交任务到线程池

二、多进程爬虫

        multiprocessing是python的多进程管理包,和threading.Thread 类似 multiprocessing模块

        multiprocessing模块可以让程序员在给定的机器上充分的利用CPU 在multiprocessing中,通过创建Process对象生成进程,然后调用 它的start()方法

2.1、多进程函数爬虫

import re  # 导入正则表达式模块  
import requests  # 导入请求库,用于发送HTTP请求  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  
from multiprocessing import Process, Manager  # 导入进程和管理器模块  
import time  # 导入时间模块,用于控制延时  def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  def get_new_url(url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取网页内容  resp = requests.get(url, headers=header)  resp.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  titles = []  # 存储章节标题  new_urls = []  # 存储章节链接  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  # 获取章节标题并打印  title = e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0]  print(title)  # 打印章节标题  titles.append(title)  # 添加标题到列表  # 构造章节链接并添加到列表  new_urls.append('https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0])  return titles, new_urls  # 返回标题和链接列表  def spider(title, new_url):  # 设置请求头,伪装成浏览器  header = {'User-Agent': UserAgent().edge}  # 发送GET请求获取章节内容  resp = requests.get(new_url, headers=header)  resp.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  safe_title = sanitize_filename(title)  # 清理标题以作为文件名  print(f"抓取中: {safe_title}")  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for i in content:  f.write(i.strip() + "\n")  # 写入内容并清理空白  time.sleep(2)  # 每次抓取后暂停2秒,防止过于频繁的请求  if __name__ == '__main__':  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  titles, new_urls = get_new_url(url)  # 获取章节标题和链接  processes = []  # 存储进程列表  # 为每个章节创建一个进程进行抓取  for title, new_url in zip(titles, new_urls):  process = Process(target=spider, args=(title, new_url))  # 创建进程  processes.append(process)  # 添加进程到列表  process.start()  # 启动进程  # 等待所有进程完成  for process in processes:  process.join()  # 等待每个进程结束

2.2、多进程类爬虫

import re  # 导入正则表达式模块  
import requests  # 导入请求库,用于发送HTTP请求  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  
from multiprocessing import Process  # 导入进程模块  
import time  # 导入时间模块,用于控制延时  class NovelSpider(Process):  # 继承自 Process  def __init__(self, title, new_url):  super().__init__()  # 调用父类的构造函数  self.title = title  # 章节标题  self.new_url = new_url  # 章节链接  self.headers = {'User-Agent': UserAgent().edge}  # 请求头  @staticmethod  def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  def run(self):  # 发送GET请求获取章节内容  resp = requests.get(self.new_url, headers=self.headers)  resp.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  safe_title = self.sanitize_filename(self.title)  # 清理标题以作为文件名  print(f"抓取中: {safe_title}")  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for i in content:  f.write(i.strip() + "\n")  # 写入内容并清理空白  time.sleep(2)  # 每次抓取后暂停2秒,防止过于频繁的请求  class NovelCrawler:  def __init__(self, base_url):  self.base_url = base_url  # 基础网址  self.headers = {'User-Agent': UserAgent().edge}  # 请求头  self.titles = []  # 存储章节标题  self.new_urls = []  # 存储章节链接  def get_new_url(self):  # 发送GET请求获取网页内容  resp = requests.get(self.base_url, headers=self.headers)  resp.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp.text)  # 解析网页内容为HTML树结构  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  title = e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0]  # 获取章节标题  print(title)  # 打印章节标题  self.titles.append(title)  # 添加标题到列表  new_url = 'https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0]  # 构造章节链接  self.new_urls.append(new_url)  # 添加链接到列表  def run(self):  self.get_new_url()  # 获取章节标题和链接  processes = []  # 存储进程列表  # 为每个章节创建一个进程进行抓取  for title, new_url in zip(self.titles, self.new_urls):  spider = NovelSpider(title, new_url)  # 创建爬虫实例  processes.append(spider)  # 添加进程到列表  spider.start()  # 启动进程  # 等待所有进程完成  for process in processes:  process.join()  # 等待每个进程结束  if __name__ == '__main__':  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  crawler = NovelCrawler(url)  # 创建爬虫控制器实例  crawler.run()  # 运行爬虫

三、协程爬虫

        网络爬虫速度效率慢,多部分在于阻塞IO这块(网络/磁盘)。在阻塞 时,CPU的中内核是可以处理别的非IO操作。因此可以考虑使用协 程来提升爬虫效率,这种操作的技术就是协程

协程一种轻量级线程,拥有自己的寄存器上下文和栈,本质是一个进程

相对于多进程,无需线程上下文切换的开销,无需原子操作锁定及同步的开销

简单的说就是让阻塞的子程序让出CPU给可以执行的子程序


一个进程包含多个线程,一个线程可以包含多个协程

多个线程相对独立,线程的切换受系统控制。 多个协程也相对独立,但是其切换由程序自己控制

pip install aiohttp 

属性或方法功能
aiohttp.ClientSession()获取客户端函数
session.get(url)发送get请求
seesion.post(url)发送post请求
resp.status获取响应状态码
resp.url获取响应url地址
resp.cookies获取响应cookie内容
resp.headers获取响应头信息
resp.read()获取响应bytes类型
resp.text()获取响应文本内容
import re  # 导入正则表达式模块  
import aiohttp  # 导入异步HTTP请求库  
import asyncio  # 导入异步库  
from fake_useragent import UserAgent  # 导入假用户代理库,用于伪装请求的用户代理  
from lxml import etree  # 导入lxml库,用于解析HTML  async def sanitize_filename(title):  # 替换 Windows 文件名中的无效字符  return re.sub(r'[<>:"/\\|?*]', '', title)  async def fetch(session, url):  # 异步获取网页内容  async with session.get(url) as response:  return await response.text()  async def get_new_url(url):  header = {'User-Agent': UserAgent().edge}  async with aiohttp.ClientSession() as session:  # 创建异步会话  resp_text = await fetch(session, url)  # 获取网页内容  resp_text.encoding = 'gbk'  # 设置网页编码为'gbk'  e = etree.HTML(resp_text)  # 解析网页内容为HTML树结构  titles = []  # 存储章节标题  new_urls = []  # 存储章节链接  # 遍历指定范围内的章节  for i in range(13, 516):  if i == 368:  # 跳过特定章节  continue  title = e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/text()")[0]  # 获取章节标题  print(title)  # 打印章节标题  titles.append(title)  # 添加标题到列表  # 构造章节链接并添加到列表  new_urls.append('https://www.bbiquge.cc/book_61985/' + e.xpath(f"//div[@id='list']/dl/dd[{i}]/a/@href")[0])  return titles, new_urls  # 返回标题和链接列表  async def spider(title, new_url):  header = {'User-Agent': UserAgent().edge}  async with aiohttp.ClientSession() as session:  # 创建异步会话  resp_text = await fetch(session, new_url)  # 异步获取章节内容  resp_text.encoding = 'gbk'  # 设置编码为'gbk'  e = etree.HTML(resp_text)  # 解析网页内容为HTML树结构  safe_title = await sanitize_filename(title)  # 清理标题以作为文件名  print(f"抓取中: {safe_title}")  # 打印当前正在抓取的章节标题  content = e.xpath("//div[@id='content']/text()")  # 获取章节内容  # 打开文件以写入章节内容  with open(f'./神印王座/{safe_title}.txt', 'a+', encoding='utf-8') as f:  for line in content:  f.write(line.strip() + "\n")  # 写入内容并清理空白  async def main():  url = 'https://www.bbiquge.cc/book_61985/'  # 目标网址  titles, new_urls = await get_new_url(url)  # 获取章节标题和链接  # 创建任务列表并并发执行  tasks = [spider(title, new_url) for title, new_url in zip(titles, new_urls)]  await asyncio.gather(*tasks)  # 使用 gather() 并发  if __name__ == '__main__':  asyncio.run(main())  # 运行主协程函数

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com