Python多线程爬虫——数据分析项目实现详解

前言

在这里插入图片描述
「作者主页」:雪碧有白泡泡
「个人网站」:雪碧的个人网站
请添加图片描述

ChatGPT体验地址

请添加图片描述

文章目录

  • 前言
  • 爬虫
  • 获取cookie
    • 网站爬取与启动
      • CSDN爬虫
      • 爬虫启动
      • 将爬取内容存到文件中
  • 多线程爬虫
    • 选择要爬取的用户
  • 线程池

爬虫

爬虫是指一种自动化程序,能够模拟人类用户在互联网上浏览网页、抓取网页内容、提取数据等操作。爬虫通常用于搜索引擎、数据挖掘、网络分析、竞争情报、用户行为分析等领域。
在这里插入图片描述
我们以爬取某个用户的博文列表并存储到文件中实现多线程爬虫为例,带大家体验爬虫的魅力

获取cookie

首先我们在爬取网站的时候首先获取cookie
在这里插入图片描述

拿我的博客主页为例,用F12打开控制台,点击网络,找到cookie
在这里插入图片描述
创建一个cookie文件,复制进去
然后从给定的cookie_path文件中读取cookie信息,并将其存储在一个字典中。函数返回这个字典。
具体如下

def get_headers(cookie_path:str):
cookies = {}
with open(cookie_path, "r", encoding="utf-8") as f:
cookie_list = f.readlines()
for line in cookie_list:
cookie = line.split(":")
cookies[cookie[0]] = str(cookie[1]).strip()
return cookies

网站爬取与启动

CSDN爬虫

class CSDN(object):
def init(self, username, folder_name, cookie_path):
# self.headers = {
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
# }
self.headers = get_headers(cookie_path)
self.s = requests.Session()
self.username = username
self.TaskQueue = TaskQueue()
self.folder_name = folder_name
self.url_num = 1
  1. headers: 这是一个字典,用于存储请求头信息。
  2. s: 这是一个会话对象,用于保持与CSDN网站的连接。
  3. username: 这是一个字符串,表示CSDN用户的用户名。
  4. TaskQueue: 这是一个任务队列对象,用于管理待访问的URL。
  5. folder_name: 这是一个字符串,表示保存爬取结果的文件夹名称。
  6. _name: 这是一个整数,表示当前保存的文件夹编号。
  7. _num: 这是一个整数,表示当前爬取的页面编号。

爬虫启动

def start(self):num = 0articles = [None]while len(articles) > 0:num += 1url = u'https://blog.csdn.net/' + self.username + '/article/list/' + str(num)response = self.s.get(url=url, headers=self.headers)html = response.textsoup = BeautifulSoup(html, "html.parser")articles = soup.find_all('div', attrs={"class":"article-item-box csdn-tracking-statistics"})for article in articles:article_title = article.a.text.strip().replace('        ',':')article_href = article.a['href']with ensure_memory(sys.getsizeof(self.TaskQueue.UnVisitedList)):self.TaskQueue.InsertUnVisitedList([article_title, article_href])
  1. 初始化一个变量num,用于表示当前访问的文章页码。
  2. 初始化一个列表articles,用于存储待处理的文章信息。
  3. 使用一个while循环,当articles列表中的文章数量大于0时,执行循环体。
  4. 更新num变量,表示当前访问的文章页码。
  5. 构造一个URL,该URL包含当前用户名、文章列表和页码。
  6. 使用requests库发送请求,并获取响应。
  7. 使用BeautifulSoup库解析HTML内容,并提取相关的文章信息。
  8. 遍历提取到的文章列表,提取文章标题和链接。
  9. 将文章标题和链接插入到任务队列TaskQueue的未访问列表中。

将爬取内容存到文件中

  1. 打印爬取开始的信息。
  2. 计算并获取存储博文列表的文件路径。
  3. 使用open函数以写入模式打开文件,并设置文件编码为utf-8
  4. 写入文件头,包括用户名和博文列表。
  5. 遍历任务队列TaskQueue中的未访问列表,将每篇文章的标题和链接写入文件。
  6. 在每篇文章标题和链接之间添加一个空行,以提高可读性。
  7. 更新一个变量_num,用于表示当前已写入的文章序号。

代码如下

def write_readme(self):print("+"*100)print("[++] 开始爬取 {} 的博文 ......".format(self.username))print("+"*100)reademe_path = result_file(self.username,file_name="README.md",folder_name=self.folder_name)with open(reademe_path,'w', encoding='utf-8') as reademe_file:readme_head = "# " + self.username + " 的博文\n"reademe_file.write(readme_head)for [article_title,article_href] in self.TaskQueue.UnVisitedList[::-1]:text = str(self.url_num) + '. [' + article_title + ']('+ article_href +')\n'reademe_file.write(text)self.url_num += 1self.url_num = 1

列表文件生成之后,我们要对每一个链接进行处理

def get_all_articles(self):try:while True:[article_title,article_href] = self.TaskQueue.PopUnVisitedList()try:file_name = re.sub(r'[\/::*?"<>|]','-', article_title) + ".md"artical_path = result_file(folder_username=self.username, file_name=file_name, folder_name=self.folder_name)md_head = "# " + article_title + "\n"md = md_head + self.get_md(article_href)print("[++++] 正在处理URL:{}".format(article_href))with open(artical_path, "w", encoding="utf-8") as artical_file:artical_file.write(md)except Exception:print("[----] 处理URL异常:{}".format(article_href))self.url_num += 1except Exception:pass
  1. 从任务队列TaskQueue中弹出未访问的文章链接和标题。
  2. 尝试获取一个文件名,该文件名由文章标题生成,以避免文件名中的特殊字符。
  3. 计算并获取存储文章的文件路径。
  4. 创建一个Markdown文件头,包括文章标题。
  5. 获取文章内容,并将其添加到Markdown文件头。
  6. 将处理后的Markdown内容写入文件。
  7. 打印正在处理的URL。
  8. 更新一个变量_num,用于表示已处理的文章数量。

多线程爬虫

实现多线程爬虫,以提高爬取速度。在循环中,会不断地创建新的线程来处理任务队列中的任务,直到任务队列为空。这样可以充分利用计算机的多核性能,提高爬取效率。

def muti_spider(self, thread_num):while self.TaskQueue.getUnVisitedListLength() > 0:thread_list = []for i in range(thread_num):th = threading.Thread(target=self.get_all_articles)thread_list.append(th)for th in thread_list:th.start()

我们在多线程爬虫的时候,要保证系统有足够的内存空间。通过使用contextlib库的contextmanager装饰器,可以轻松地实现上下文管理,确保内存分配和释放的正确性。

lock = threading.Lock()
total_mem= 1024 * 1024 * 500 #500MB spare memory
@contextlib.contextmanager
def ensure_memory(size):global total_memwhile 1:with lock:if total_mem > size:total_mem-= sizebreaktime.sleep(5)yield with lock:total_mem += size

__enter__方法中,使用with lock语句模拟加锁,确保在执行内存分配操作时,不会发生竞争条件。然后判断当前系统的总内存是否大于所需分配的内存空间,如果大于,则减少总内存,并跳出循环。

选择要爬取的用户

def spider_user(username: str, cookie_path:str, thread_num: int = 10, folder_name: str = "articles"):if not os.path.exists(folder_name):os.makedirs(folder_name)csdn = CSDN(username, folder_name, cookie_path)csdn.start()th1 = threading.Thread(target=csdn.write_readme)th1.start()th2 = threading.Thread(target=csdn.muti_spider, args=(thread_num,))th2.start()
  1. 检查文件夹folder_name是否存在,如果不存在,则创建该文件夹。
  2. 创建一个CSDN对象csdn,用于模拟用户登录和爬取文章。
  3. 创建一个线程th1,目标为_readme
  4. 创建一个线程th2,目标为_spider,并传入参数(thread_num,),用于指定线程数量。

这个函数的目的是爬取指定用户的CSDN博客文章,并将文章保存到文件夹folder_name中。通过创建线程,可以实现多线程爬虫,提高爬取速度。

线程池

线程池存储爬虫代理 IP 的数据库或集合。在网络爬虫中,由于目标网站可能会针对同一 IP 地址的访问频率进行限制,因此需要使用池来存储多个代理 IP 地址,以实现 IP 地址的轮换和代理。池可以提高爬虫的稳定性和效率,避免因为 IP 地址被封禁而导致的爬虫失效。
爬虫和池是爬虫领域中不可或缺的概念,池能够提高爬虫的稳定性和效率,同时帮助爬虫更好地适应目标的反爬虫策略。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/630801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kylin 安装novnc 远程访问

noVNC可以使用浏览器直接访问服务器&#xff0c;而不需要使用VNC客户端。 1.初始环境 关闭防火墙或允许IP访问本机 2.安装依赖 dnf install -y tigervnc-server git 3.git下载novnc git clone https://github.com/novnc/noVNC.git 4.配置信任证书 openssl req -new -x509 …

RabbitMQ使用篇

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…

USB转SPI USB转IIC 串口转SPI串口转IIC SPI I2C模块

一款支持USB转SPI、USB转I2C、USB转GPIO、USB转PWM、USB转ADC的模块。提供上位机工具&#xff0c;开发协议。 资料下载&#xff0c;链接&#xff1a;https://pan.baidu.com/s/1sw3RCMwjhrMO4qzUBq9bjA 提取码&#xff1a;qzjp 概述 串口转多协议模组为了客户调试一些功能…

PICO Developer Center 创建和调试 ADB 命令

PICO 开发者中心概览 ADB 是一个轻量级的 Android 调试桥(Android Debug Bridge&#xff0c;简称 ADB)&#xff0c;用于与 Android 设备进行通信和调试。ADB提供了许多有用的功能&#xff0c;使开发人员能够轻松地管理和调试设备上的应用程序。 你可以使用 PDC 工具来调试系统…

阿里云服务器4核8G配置收费标准及新老用户优惠价格整理

阿里云服务器4核8g配置云服务器u1价格是955.58元一年&#xff0c;4核8G配置还可以选择ECS计算型c7实例、计算型c8i实例、计算平衡增强型c6e、ECS经济型e实例、AMD计算型c8a等机型等ECS实例规格&#xff0c;规格不同性能不同&#xff0c;价格也不同&#xff0c;阿里云服务器网al…

使用 vsCode创建GO项目

最近回顾了一下go的使用&#xff1a;具体操作看下面的参考连接&#xff0c;下面只描述一些踩过的坑&#xff1a; 1. go安装配置 安装go->配置go环境变量 推荐官网下载&#xff0c;速度很快&#xff1b; 这里需要配置五个参数&#xff1a;GOPATH/GOROOT/Path、GO111MODULE/…

如何快速打造属于自己的接口自动化测试框架

1 接口测试 接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。 接口自动化相对于UI自动化来说&#xff0c;属于更底层的测试&#xff0c;这样带来的好处就是测试收益更大&#xff…

WordPress设置回收站自动清理天数的插件Change Empty Trash Time

前面boke112百科跟大家分享的『WordPress回收站自动清空时间&#xff1f;如何关闭回收站或设置自动清理天数&#xff1f;』一文&#xff0c;就介绍了可以添加一行代码实现关闭或设置回收站自动清理时间&#xff0c;也可以通过安装Change Empty Trash Time插件来实现。 今天bok…

【论文阅读】One For All: Toward Training One Graph Model for All Classification Tasks

目录 0、基本信息1、研究动机2、创新点——One For All &#xff1a;unique features3、准备4、具体实现4.1、用TAGs统一来自不同领域的图数据4.2、用NOI&#xff08;NODES-OF-INTEREST&#xff09;统一不同图任务4.2.1、NOI子图4.2.2、NOI提示结点 4.3、用于图的上下文学习&am…

java大数据hadoop2.9.2 Java编写Hadoop分析平均成绩

1、准备文件&#xff0c;例如score.txt&#xff0c;内容如下&#xff1a; zs k1 88 ls k1 98 ww k1 78 zs k2 88 ls k2 98 ww k2 78 zs k3 88 ls k3 98 ww k3 78 2、创建maven项目 <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common --><d…

【XTuner 大模型单卡低成本微调实战】学习笔记

参考学习教程【XTuner 大模型单卡低成本微调实战】 理论 Finetune简介 大语言模型 微调模式 增量预训练 指令跟随微调 LoRA和QLoRA Xtuner介绍 实战 自定义微调 用 Medication QA 数据集进行微调 将数据转为 XTuner 的数据格式 目标格式&#xff1a;(.jsonL) 写提示词请C…

ChatGPT 商业提示词攻略书

原文&#xff1a;ChatGPT Business Prompt Playbook 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、书系介绍 人工智能发展迅速。非常迅速。 所以我希望你做两件事&#xff1a; (1) 在 Twitter 上关注我&#xff1a;iamkylebalmer (2) 订阅我的免费电子邮件通…

SpringMVC JSON数据处理见解6

6.JSON数据处理 6.1.添加json依赖 springmvc 默认使用jackson作为json类库,不需要修改applicationContext-servlet.xml任何配置&#xff0c;只需引入以下类库springmvc就可以处理json数据&#xff1a; <!--spring-json依赖--> <dependency><groupId>com.f…

MySQL窗口函数(MySQL Window Functions)

1、窗口函数基本概念 官网地址&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/window-functions.html 窗口可以理解为 记录集合&#xff0c;窗口函数就是在满足某种条件的记录集合上执行的特殊函数。 即&#xff1a;每条记录都要在此窗口内执行函数。 静态窗口&#x…

springboot集成shiro+前端vue,前后端分离项目遇到跨域以及sessionid拿不到等问题

近期在写前后端分离的项目&#xff0c;由于前后端分离导致原来使用的shiro配置无法满足现有系统要求。同时在前后端分离项目中存在的一些问题。例如&#xff0c;一些用户信息需要存储在后端方便进行安全性判断&#xff0c;但这些存储在后端的session前端却获取不到&#xff08;…

Docker本地私有仓库搭建配置指导

一、说明 因内网主机需要拉取镜像进行Docker应用&#xff0c;因此需要一台带外主机作为内网私有仓库来提供内外其他docker业务主机使用。参考架构如下&#xff1a; 相关资源&#xff1a;加密、Distribution registry、Create and Configure Docker Registry、Registry部署、D…

K8s-架构

一、K8s节点划分 K8s集群包含Master(控制节点)和Node(工作节点)&#xff0c;应用部署在Node节点上。 集群架构图&#xff1a; 二、Master节点 Master节点分成四个组件&#xff1a;scheduler、ApiServer、Controller Manager、ETCD。类似三层结构&#xff0c;controller&#…

2024年外贸新兴市场有哪些 | 箱讯科技国际贸易平台

当前欧美市场经济增速放缓&#xff0c;通胀持续高位导致物价普遍上涨&#xff0c;进一步引发消费疲软。此外&#xff0c;受原材料价格、劳动力、土地等经营成本上升影响&#xff0c;外贸出口企业利润被进一步压缩。 困顿之中&#xff0c;新兴市场成为破局关键&#xff0c;巨大的…

Mysql流程控制函数

1概述 Mysql中的流程控制函数非常重要&#xff0c;可以根据不同的条件&#xff0c;执行不同的流程转换&#xff0c;可以在SQL语句中实现不同的条件选择。MySQL中的流程处理函数主要包括IF()、IFNULL()和CASE()函数。 1.1 IF函数 SELECT IF(1 > 0, 正确, 错误);1.2 IFNULL…

rabbitmq基础教程(ui,java,springamqp)

概述&#xff1a;安装看我上篇文章Docker安装rabbitmq-CSDN博客 任务一 创建一个队列 这样创建两个队列 在amq.fanout交换机里面发送数据 模拟发送数据 发送消息&#xff0c;发现一下信息&#xff1a; 所以得出理论&#xff0c;消息发送是先到交换机&#xff0c;然后由交换机…