使用 Python 爬取某网站简历模板(bs4/lxml+协程)


使用 Python 爬取站长素材简历模板


简介

在本教程中,我们将学习如何使用 Python 来爬取站长素材网站上的简历模板。我们将使用requestsBeautifulSoup库来发送 HTTP 请求和解析 HTML 页面。本教程将分为两个部分:第一部分是使用BeautifulSoup的方法,第二部分是使用lxml的方法,并比较两者的差异。

环境准备

首先,确保你已经安装了 Python。然后,安装以下库:

pip install requests beautifulsoup4 lxml

方法一:使用 BeautifulSoup

1.导入库

import requests
from bs4 import BeautifulSoup
import os

2.创建文件夹用于保存爬取的简历图片

if not os.path.exists("resume_templates_images"):os.makedirs("resume_templates_images")

3.爬取第一页

first_page_url = "https://sc.chinaz.com/jianli/free.html"
response = requests.get(first_page_url)
response.encoding = 'utf-8'if response.status_code == 200:soup = BeautifulSoup(response.text, 'html.parser')templates = soup.find_all('div', class_='box col3 ws_block')for template in templates:link = template.find('a', target='_blank')['href']img = template.find('img')['src']if img.startswith('//'):img = 'https:' + imgtitle = template.find('p').find('a').text.strip()img_response = requests.get(img)if img_response.status_code == 200:img_name = f"{title.replace(' ', '_')}.jpg"img_path = os.path.join("resume_templates_images", img_name)with open(img_path, 'wb') as f:f.write(img_response.content)else:print(f"下载图片 {img} 失败,状态码: {img_response.status_code}")

4.爬取第二页到第五页

在这里插入代base_url = "https://sc.chinaz.com/jianli/free_"
for page_num in range(2, 6):url = f"{base_url}{page_num}.html"response = requests.get(url)response.encoding = 'utf-8'if response.status_code == 200:soup = BeautifulSoup(response.text, 'html.parser')templates = soup.find_all('div', class_='box col3 ws_block')for template in templates:link = template.find('a', target='_blank')['href']img = template.find('img')['src']if img.startswith('//'):img = 'https:' + imgtitle = template.find('p').find('a').text.strip()img_response = requests.get(img)if img_response.status_code == 200:img_name = f"{title.replace(' ', '_')}.jpg"img_path = os.path.join("resume_templates_images", img_name)with open(img_path, 'wb') as f:f.write(img_response.content)else:print(f"下载图片 {img} 失败,状态码: {img_response.status_code}")
码片

方法二:使用 lxml

first_page_url = "https://sc.chinaz.com/jianli/free.html"
response = requests.get(first_page_url)
response.encoding = 'utf-8'if response.status_code == 200:tree = etree.HTML(response.text)templates = tree.xpath('//div[@class="box col3 ws_block"]')for template in templates:link = template.xpath('.//a[@target="_blank"]/@href')[0]img = template.xpath('.//img/@src')[0]if img.startswith('//'):img = 'https:' + imgtitle = template.xpath('.//p/a[@class="title_wl"]/text()')[0].strip()img_response = requests.get(img)if img_response.status_code == 200:img_name = f"{title.replace(' ', '_')}.jpg"img_path = os.path.join("resume_templates_images", img_name)with open(img_path, 'wb') as f:f.write(img_response.content)else:print(f"下载图片 {img} 失败,状态码: {img_response.status_code}")

同方法一,但使用lxmlxpath方法。

方法比较

• 解析速度:lxml通常比BeautifulSoup快,特别是在处理大型 HTML 文档时。

• 易用性:BeautifulSoup提供了更直观的方法来查找元素,如findfind_all,而lxml使用xpath,这可能需要更多的学习。

• 灵活性:xpath在定位复杂的 HTML 结构时更加灵活,但也需要更复杂的查询。

通过运行我们发现这段代码的执行时间较长,那么我们有没有方法来缩短运行时间呢

import asyncio
import aiohttp
from bs4 import BeautifulSoup
import os
import time  # 导入time模块来记录时间# 创建一个文件夹resume_templates_images用于保存图片
if not os.path.exists("resume_templates_images"):os.makedirs("resume_templates_images")# 用于存储所有页面的模板数据
all_template_data = []async def fetch(session, url):async with session.get(url) as response:return await response.text()async def parse_page(session, url):soup = BeautifulSoup(await fetch(session, url), 'html.parser')templates = soup.find_all('div', class_='box col3 ws_block')for template in templates:link = template.find('a', target='_blank')['href']img = template.find('img')['src']if img.startswith('//'):img = 'https:' + imgtitle = template.find('p').find('a').text.strip()async with session.get(img) as img_response:if img_response.status == 200:img_name = f"{title.replace(' ', '_')}.jpg"img_path = os.path.join("resume_templates_images", img_name)with open(img_path, 'wb') as f:f.write(await img_response.read())all_template_data.append({'title': title,'img_url': img,'link': link})async def main():start_time = time.time()  # 记录开始时间async with aiohttp.ClientSession() as session:# 处理第一页await parse_page(session, "https://sc.chinaz.com/jianli/free.html")# 处理第二页到第五页for page_num in range(2, 6):url = f"https://sc.chinaz.com/jianli/free_{page_num}.html"await parse_page(session, url)# 输出所有页面的模板数据for idx, data in enumerate(all_template_data, 1):print(f"模板 {idx}:")print(f"名称: {data['title']}")print(f"图片链接: {data['img_url']}")print(f"模板链接: {data['link']}")print("=" * 50)end_time = time.time()  # 记录结束时间run_time = end_time - start_time  # 计算运行时间print(f"程序运行时间:{run_time:.2f}秒")if __name__ == "__main__":asyncio.run(main())

这段代码是一个使用asyncioaiohttp库来异步爬取站长素材网站上的简历模板的 Python 脚本。以下是代码的详细解释和如何加快爬取速度的说明:

• parse_page 函数:一个异步函数,用于解析页面内容,提取模板链接和图片链接,并下载图片。

• 异步 I/O:使用asyncioaiohttp可以实现异步 I/O 操作,这意味着在等待网络响应时,程序可以执行其他任务,而不是被阻塞。这样可以显著提高爬取效率,特别是在需要处理多个页面时。
在这里插入图片描述
这段代码是顺序并发执行执行每个页面的爬取,有没有更快的方式——并发执行
• 并发请求:使用asyncio.gather来同时启动多个parse_page任务。

修改代码以实现并发请求

以下是如何修改main函数来实现并发请求:

async def main():start_time = time.time()  # 记录开始时间async with aiohttp.ClientSession() as session:# 处理第一页tasks = [parse_page(session, "https://sc.chinaz.com/jianli/free.html")]# 处理第二页到第五页,并发执行for page_num in range(2, 6):url = f"https://sc.chinaz.com/jianli/free_{page_num}.html"tasks.append(parse_page(session, url))# 等待所有页面处理完成await asyncio.gather(*tasks)# 输出所有页面的模板数据for idx, data in enumerate(all_template_data, 1):print(f"模板 {idx}:")print(f"名称: {data['title']}")print(f"图片链接: {data['img_url']}")print(f"模板链接: {data['link']}")print("=" * 50)end_time = time.time()  # 记录结束时间run_time = end_time - start_time  # 计算运行时间print(f"程序运行时间:{run_time:.2f}秒")if __name__ == "__main__":asyncio.run(main())

在这个修改后的版本中,所有的页面爬取任务都被添加到一个列表中,然后使用asyncio.gather来并发执行这些任务。这样可以同时发送多个请求,而不是等待一个请求完成后再发送下一个请求,从而加快整体的爬取速度。
在这里插入图片描述
在这里插入图片描述

import asyncio
import aiohttp
from bs4 import BeautifulSoup
import os
import time
import aiofiles# 创建一个文件夹resume_templates_images用于保存图片
if not os.path.exists("resume_templates_images"):os.makedirs("resume_templates_images")# 用于存储所有页面的模板数据
all_template_data = []
#async with aiohttp.ClientSession() as session
async def fetch(session, url):async with session.get(url) as response:return await response.text()#返回字符串形式的响应数据async def parse_page(session, url):soup = BeautifulSoup(await fetch(session, url), 'html.parser')templates = soup.find_all('div', class_='box col3 ws_block')for template in templates:link = template.find('a', target='_blank')['href']img = template.find('img')['src']if img.startswith('//'):img = 'https:' + imgtitle = template.find('p').find('a').text.strip()async with session.get(img) as img_response:if img_response.status == 200:file_type = ".jpg.rar"#  以rar压缩文件的形式储存img_name = f"{title.replace(' ', '_')+file_type}"#  更改保存的格式仅需修改img_path = os.path.join("resume_templates_images", img_name)async with aiofiles.open(img_path, 'wb') as f:await f.write(await img_response.read())# read()返回二进制数据all_template_data.append({'title': title,'img_url': img,'link': link})async def main():start_time = time.time()  # 记录开始时间async with aiohttp.ClientSession() as session:# 创建任务列表tasks = []# 处理第一页task = asyncio.create_task(parse_page(session, "https://sc.chinaz.com/jianli/free.html"))tasks.append(task)# 处理第二页到第五页,并发执行for page_num in range(2, 6):url = f"https://sc.chinaz.com/jianli/free_{page_num}.html"task = asyncio.create_task(parse_page(session, url))tasks.append(task)# 等待所有页面处理完成  挂起任务列表 asyncio.gather 是 Python asyncio 模块中的一个函数,它用于并发地运行多个协程,并且等待它们全部完成。#  asyncio.gather 的作用类似于 asyncio.wait,但它不仅等待协程完成,还会返回一个包含所有结果的列表。await asyncio.gather(*tasks)# 输出所有页面的模板数据for idx, data in enumerate(all_template_data, 1):print(f"模板 {idx}:")print(f"名称: {data['title']}")print(f"图片链接: {data['img_url']}")print(f"模板链接: {data['link']}")print("=" * 50)end_time = time.time()  # 记录结束时间run_time = end_time - start_time  # 计算运行时间print(f"程序运行时间:{run_time:.2f}秒")if __name__ == "__main__":asyncio.run(main())

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

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

相关文章

什么是厄尔米特(Hermitian)矩阵?

厄米矩阵(Hermitian Matrix)定义 在数学和物理中,厄米矩阵是满足以下条件的复方阵: A A † \mathbf{A}\mathbf{A}^\dagger AA† 其中, A † \mathbf{A}^\dagger A†表示矩阵 A \mathbf{A} A的共轭转置,即…

HCIA-Access V2.5_2_2网络通信基础_TCP/IP协议栈报文封装

TCP/IP协议栈的封装过程 用户从应用层发出数据先会交给传输层,传输层会添加TCP或者UDP头部,然后交给网络层,网络层会添加IP头部,然后交给数据链路层,数据链路层会添加以太网头部和以太网尾部,最后变成01这样…

爬虫获取的数据能否用于商业分析?

根据搜索结果,爬虫获取的数据能否用于商业分析,主要取决于以下几个因素: 数据的合法性与合规性: 爬虫技术本身并不违法,关键在于使用的方式和目的。爬虫技术的使用必须遵守相关法律法规,如《反不正当竞争法…

数据湖治理最佳实践

如果没有最佳实践,存储可能会变得无法维护。自动化数据质量、生命周期和隐私功能可持续清理/移动数据湖中的数据。数据湖正成为企业从大数据中提取价值的一种日益可行的解决方案,对于早期采用者和新用户来说都是合理的下一步。在独立的逻辑区域中随时可用…

《Vue进阶教程》第六课:computed()函数详解(上)

往期内容: 《Vue零基础入门教程》合集(完结) 《Vue进阶教程》第一课:什么是组合式API 《Vue进阶教程》第二课:为什么提出组合式API 《Vue进阶教程》第三课:Vue响应式原理 《Vue进阶教程》第四课&#…

根据PDF模板单个PDF导出到浏览器和多个PDF打包ZIP导出到浏览器

一、单个PDF导出到浏览器 /*** * param templatePath 模板路径* param fileName 文件名称* param data 填充文本* param images 填充图片* param response* throws IOException*/public static void generateTempPDF(String templatePath, String fileName, Map<String, S…

ssd202d-badblock-坏块检测

这边文章讲述的是坏快检测功能 思路&#xff1a; 1.第一次烧录固件会实现跳坏块&#xff0c;但是后续使用会导致坏块的产生&#xff1b; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum //坏块个数 lb_badoff //坏块所在位置 2.第一次开机会根据lb_badnum是否…

Tornado 异步编程全解析

一、Tornado 异步基础 核心概念 IOLoop&#xff1a; 是 Tornado 的核心事件循环&#xff0c;负责处理网络 I/O、定时器等事件。它不断地循环监听事件&#xff0c;一旦有事件就绪就调用相应的回调函数。可以在一个进程中创建多个 IOLoop&#xff0c;但通常一个应用使用一个主 IO…

Windows桌面系统管理2:VMware Workstation使用和管理

Windows桌面系统管理0:总目录-CSDN博客 Windows桌面系统管理1:计算机硬件组成及组装-CSDN博客 Windows桌面系统管理2:VMware Workstation使用和管理 Windows桌面系统管理3:Windows 10操作系统部署与使用-CSDN博客 Windows桌面系统管理4:Windows 10操作系统运维管理-…

鸿蒙ArkTS如何实现数据可视化:饼状图/柱状图/折线图

鸿蒙数据可视化系列 在我们鸿蒙APP开发中&#xff0c;经常需要使用到一些图表的开发&#xff0c;本文主要介绍使用 McCharts 框架绘制柱状图的方法 配套指导视频地址&#xff1a;鸿蒙数据可视化系列-McCharts使用介绍_哔哩哔哩_bilibili 1. 第三方库介绍 1.1. McCharts Mc…

基于go语言的开源调度系统整理

pink https://github.com/busgo/pink 通过Web界面管理操作简单方便&#xff0c;支持各种任务 高可用可以部署 n 台调度集群节点&#xff0c;保证没有单点故障。 部署简单、仅仅需要一个执行文件即可运行。 集成方便&#xff0c;统一语言无关的任务抽象&#xff0c;接入不同语言…

多个终端查看的history不一样,如何确保多个终端会话之间的 history 一致,减少历史记录差异

问题&#xff1a; 在使用 Linux 系统时&#xff0c;history 命令显示的历史记录通常是与当前终端会话相关的。这就意味着&#xff0c;如果你在多个终端中打开会话&#xff0c;它们显示的历史记录可能不完全相同。这个问题通常是由以下原因引起的&#xff1a; 原因&#xff1a…

yolov8 转华为昇腾om脚本

目录 yolov8 转华为昇腾 om脚本 测试ok 推理demo: yolov8 转华为昇腾 om脚本 测试ok import sys import osos.chdir(os.path.dirname(os.path.abspath(__file__)))import torchcurrent_dir = os.path.dirname(os.path.abspath(__file__))paths = [os.path.abspath(__file__)…

unity打包sdk热更新笔记

Unity3D项目Plugins目录组织 https://blog.csdn.net/linxinfa/article/details/102978005 IPreprocessBuild 继承提供打包前&#xff0c;打包后接口 BuildAssetBundles UnityWebRequest’s DownloadHandlerAssetBundle / LoadFromFile / LoadFromMemoryAsync 数据完整性校…

12.11-12.12总结(约瑟夫问题 机器翻译 滑动窗口)

12.11 刷题 《算法竞赛》这本书看了很多了&#xff0c;但是题目没咋做&#xff0c;所以今天来刷一下题 P1996约瑟夫问题 还依稀记得大一的时候被约瑟夫支配的恐惧&#xff08;哭&#xff09;&#xff0c;但是现在做就感觉很简单&#xff08;虽然也敲了一会&#xff0c;今早感…

git SSL certificate problem: unable to get local issuer certificate

Git 客户端将会验证服务器端提供的SSL证书是否由受信任的证书颁发机构&#xff08;Certification Authority&#xff0c;CA&#xff09;签发。如果Git客户端无法找到或验证本地签发者证书&#xff0c;就会出现 unable to get local issuer certificate 或类似的错误。 该问题一…

使用秘钥登录服务器

在我们测试或生产环境中&#xff0c;为了服务器安全性&#xff0c;有时可能需要以 SSH 密钥的方式登录服务器&#xff0c;接下来&#xff0c;将演示如何通过 SSH 私钥的方式来远程服务器。 一、远程服务器生成密钥对 1、首先在目标远程服务器下生成 SSH 密钥对 ssh-keygen然…

css设置透明的几种办法

在CSS中&#xff0c;有几种方法可以设置元素的透明度。以下是主要的几种方式&#xff1a; 1. 使用 opacity 属性 定义&#xff1a;opacity 属性用于设置元素的整体透明度&#xff0c;包括其内容和背景。取值范围&#xff1a;取值从0&#xff08;完全透明&#xff09;到1&…

4,双向带头循环链表

目录 1&#xff0c;双向带头循环链表的定义 2&#xff0c;双向带头循环链表的实现 A&#xff0c;函数的声明 B&#xff0c;函数的定义 1&#xff0c;双向带头循环链表的定义 带头双向循环链表&#xff1a;结构复杂&#xff0c;一般用在单独存储数据。实际中使用的链表数据…

谷粒商城—分布式基础

1. 整体介绍 1)安装vagrant 2)安装Centos7 $ vagrant init centos/7 A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on…