热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【爬虫实战案例1】基于BeautifulSoup+Re+Pandas简单实现爬虫需求

前言分享一篇使用部分爬虫技术简单实现对媒体类网页按需求爬取文章并保存到本地指定文件夹的案例,仅供相关学习者参考,学习过程切勿对网站频繁访问而造成网页瘫

前言 

分享一篇使用部分爬虫技术简单实现对媒体类网页按需求爬取文章并保存到本地指定文件夹的案例,仅供相关学习者参考,学习过程切勿对网站频繁访问而造成网页瘫痪,量力而为!!!

BeautifulSoup的简单使用:https://inganxu.blog.csdn.net/article/details/122783587




爬取需求

爬取地址:建筑档案-建筑行业全产业链内容共建平台

爬取涉及技术:Requests(访问)、BeautifulSoup、Re(解析)、Pandas(保存)

爬取目的:仅用于练习巩固爬虫技术

爬取目标:


  1. 将网页首页中每个文章的标题、作者、发布时间、文章链接保存到指定位置的excel文件中,excel名称为data
  2. 将每个文章的文本保存到指定位置的文档中,并以文章标题命名
  3. 将每个文章的图片保存到指定位置的文件夹中,并以文章标题 + 图片序号命名



爬取思路

发起首页网页请求,获取响应内容

解析首页网页数据,获取文章的标题、作者、发布时间、文章链接信息

汇总网站首页信息,保存到excel

        发起文章网页请求,获取响应内容

        解析文章网页数据,获取文章的文本图片链接信息

        保存文章内容到指定文档

                发起图片网页请求,获取响应内容

                保存图片到指定文件夹




代码讲解

下面以爬虫思路的顺序讲解每个步骤的实现方式以及注意事项


步骤一:导入相关库

import requests # 用于发起网页请求,返回响应内容
import pandas as pd # 生成二维数据,保存到excel中
import os # 文件保存
import time # 减慢爬虫速度
import re # 提取解析内容
from bs4 import BeautifulSoup # 对响应内容解析数据

没有相关的库就自行安装

win键+r,调出CMD窗口,输入以下代码

pip install 欠缺的库名



步骤二:设置防识别爬虫措施

"""
记录爬虫时间
设置访问网页基础信息
"""
start_time = time.time()
start_url = "https://www.jzda001.com"
header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'}

hearder:表头,自己复制浏览器的表头,实在不会找就直接复制我的用




步骤三:主页访问,解析响应内容

response = requests.get(url=start_url, headers=header) # 发起请求
html = response.text # 提取响应内容
soup = BeautifulSoup(html, 'lxml') # 解析响应内容
content = soup.find_all('div', attrs={'class': 'content-left'})[0] # 筛选并提取仅需爬虫的内容# 使用列表来装载爬虫信息
item = {}
href_list = []
title_list = []
author_list = []
releasetime_list = []# 获取文章链接
for href in content.find_all('a', href=re.compile('^/index/index/details')):if href['href'] not in href_list:href_list.append(href['href'])# 获取文章标题
for title in content.find_all('p', class_=re.compile('(twoline|sub oneline|oneline)'))[:-1]:title_list.append(title.text)# 获取文章作者和发布时间
for author_time in content.find_all(&#39;p&#39;, attrs&#61;{&#39;class&#39;: &#39;name&#39;}):if len(author_list) <20:author &#61; re.findall(r&#39;(?<&#61;\s)\D&#43;(?&#61;\s\.)&#39;, author_time.text)[0]author_list.append(author.replace(&#39; &#39;, &#39;&#39;))if len(releasetime_list) <20:time &#61; re.findall(r&#39;\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}&#39;, author_time.text)releasetime_list.append(time[0])

解析过程发现获取的内容头部或尾部有不需要的信息&#xff0c;因此使用列表切片方式将元素剔除掉




步骤四&#xff1a;数据清洗

# 主页面数据清洗
author_clear &#61; []
for i in author_list:if i !&#61; &#39;.&#39;:author_clear.append(i.replace(&#39;\n&#39;, &#39;&#39;).replace(&#39; &#39;, &#39;&#39;))
author_list &#61; author_clear
time_clear &#61; []
for j in releasetime_list:time_clear.append(j.replace(&#39;\n&#39;, &#39;&#39;).replace(&#39; &#39;, &#39;&#39;).replace(&#39;:&#39;, &#39;&#39;))
releasetime_list &#61; time_clear
title_clear &#61; []
for n in title_list:title_clear.append(n.replace(&#39;&#xff1a;&#39;, &#39; &#39;).replace(&#39;&#xff01;&#39;, &#39; &#39;).replace(&#39;|&#39;, &#39; &#39;).replace(&#39;/&#39;, &#39; &#39;).replace(&#39; &#39;, &#39; &#39;))
title_list &#61; title_clear

查看网页结构&#xff0c;可以看到标题、作者、发布时间都有一些系统敏感字符&#xff08;影响后续无法创建文件夹&#xff09;

所以&#xff0c;需要把解析到的数据作数据清洗后才能使用 




步骤五&#xff1a;访问文章链接并解析提取响应内容

通过对比网页结构的&#64;href属性链接和文章的真实链接&#xff0c;可知解析到的url需要拼接网址首页进去

 


# 访问文章并保存文本信息和图片到指定文件夹
for nums in range(20):text_list &#61; []img_url_list &#61; []article_url &#61; start_url &#43; href_list[nums]response_url &#61; requests.get(article_url, headers&#61;header, timeout&#61;1)html_text &#61; response_url.textsoup_article &#61; BeautifulSoup(html_text, &#39;lxml&#39;)# 获取子页面文本&#xff08;用find_all方法&#xff09;content_article &#61; soup_article.find_all(&#39;div&#39;, attrs&#61;{&#39;class&#39;: &#39;content&#39;})[-1]text &#61; &#39;&#39;for i in content_article:text &#61; text &#43; i.texttext_list.append(text)# 获取子页面图片链接&#xff08;用select方法&#xff09;soup_article_url &#61; content_article.select(&#39;.pgc-img > img&#39;)for url in soup_article_url:img_url_list.append(url[&#39;src&#39;])

拼接文本内容是因为获取到的文本信息是一段一段分开的&#xff0c;需要拼接在一起&#xff0c;才是完整的文章文本信息




步骤六&#xff1a;创建多层文件夹

新建多层文件夹file_name &#61; "建筑档案爬虫文件夹" # 文件夹名称path &#61; r&#39;d:/&#39; &#43; file_nameurl_path_file &#61; path &#43; &#39;/&#39; &#43; title_list[nums] &#43; &#39;/&#39; # 拼接文件夹地址if not os.path.exists(url_path_file):os.makedirs(url_path_file)

因为创建的文件夹是&#xff1a;“./爬虫文件夹名称/文章标题名称/”&#xff0c;所以需要用os.makedirs来创建多层文件夹

注意文件名称最后带 “/”




步骤七&#xff1a;保存子页面图片

当建立好文件夹后&#xff0c;就开始访问每个文章的图片链接&#xff0c;并且保存下来

# 保存子页面图片for index, img_url in enumerate(img_url_list):img_rep &#61; requests.get(img_url, headers&#61;header, timeout&#61;5) # 设置超时时间index &#43;&#61; 1 # 每保存图片一次&#xff0c;显示数量&#43;1img_name &#61; title_list[nums] &#43; &#39; 图片&#39; &#43; &#39;{}&#39;.format(index) # 图片名称img_path &#61; url_path_file &#43; img_name &#43; &#39;.png&#39; # 图片地址with open(img_path, &#39;wb&#39;) as f:f.write(img_rep.content) # 以二进制的方式写入f.close()



步骤八&#xff1a;保存子页面文本

先保存文本再保存图片也可以&#xff0c;需要注意两者的写入方式

# 保存网页文本txt_name &#61; str(title_list[nums] &#43; &#39; &#39; &#43; author_list[nums] &#43; &#39; &#39; &#43; releasetime_list[nums]) # 文本名称txt_path &#61; url_path_file &#43; &#39;/&#39; &#43; txt_name &#43; &#39;.txt&#39; # 文本地址with open(txt_path, &#39;w&#39;, encoding&#61;&#39;utf-8&#39;) as f:f.write(str(text_list[0]))f.close()



步骤九&#xff1a;文章信息汇总

将网站首页的所有文章标题、作者、发布时间、文章链接都保存到一个excel文件夹中

# 主页面信息保存
data &#61; pd.DataFrame({&#39;title&#39;: title_list,&#39;author&#39;: author_list,&#39;time&#39;: releasetime_list,&#39;url&#39;: href_list})
data.to_excel(&#39;{}./data.xls&#39;.format(path), index&#61;False)



完整代码&#xff08;面向过程版&#xff09;

# &#xff01;/usr/bin/python3.9
# -*- coding:utf-8 -*-
# &#64;author:inganxu
# CSDN:inganxu.blog.csdn.net
# &#64;Date:2022年2月3日import requests # 用于发起网页请求&#xff0c;返回响应内容
import pandas as pd # 生成二维数据&#xff0c;保存到excel中
import os # 文件保存
import time # 减慢爬虫速度
import re # 提取解析内容
from bs4 import BeautifulSoup # 对响应内容解析数据start_time &#61; time.time()start_url &#61; "https://www.jzda001.com"
header &#61; {&#39;user-agent&#39;: &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36&#39;}response &#61; requests.get(url&#61;start_url, headers&#61;header) # 发起请求
html &#61; response.text # 提取响应内容
soup &#61; BeautifulSoup(html, &#39;lxml&#39;) # 解析响应内容
content &#61; soup.find_all(&#39;div&#39;, attrs&#61;{&#39;class&#39;: &#39;content-left&#39;})[0] # 筛选并提取仅需爬虫的内容# 使用列表来装载爬虫信息
item &#61; {}
href_list &#61; []
title_list &#61; []
author_list &#61; []
releasetime_list &#61; []# 获取文章链接
for href in content.find_all(&#39;a&#39;, href&#61;re.compile(&#39;^/index/index/details&#39;)):if href[&#39;href&#39;] not in href_list:href_list.append(href[&#39;href&#39;])# 获取文章标题
for title in content.find_all(&#39;p&#39;, class_&#61;re.compile(&#39;(twoline|sub oneline|oneline)&#39;))[:-1]:title_list.append(title.text)# 获取文章作者和发布时间
for author_time in content.find_all(&#39;p&#39;, attrs&#61;{&#39;class&#39;: &#39;name&#39;}):if len(author_list) <20:author &#61; re.findall(r&#39;(?<&#61;\s)\D&#43;(?&#61;\s\.)&#39;, author_time.text)[0]author_list.append(author.replace(&#39; &#39;, &#39;&#39;))if len(releasetime_list) <20:time &#61; re.findall(r&#39;\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}&#39;, author_time.text)releasetime_list.append(time[0])# 主页面数据清洗
author_clear &#61; []
for i in author_list:if i !&#61; &#39;.&#39;:author_clear.append(i.replace(&#39;\n&#39;, &#39;&#39;).replace(&#39; &#39;, &#39;&#39;))
author_list &#61; author_clear
time_clear &#61; []
for j in releasetime_list:time_clear.append(j.replace(&#39;\n&#39;, &#39;&#39;).replace(&#39; &#39;, &#39;&#39;).replace(&#39;:&#39;, &#39;&#39;))
releasetime_list &#61; time_clear
title_clear &#61; []
for n in title_list:title_clear.append(n.replace(&#39;&#xff1a;&#39;, &#39; &#39;).replace(&#39;&#xff01;&#39;, &#39; &#39;).replace(&#39;|&#39;, &#39; &#39;).replace(&#39;/&#39;, &#39; &#39;).replace(&#39; &#39;, &#39; &#39;))
title_list &#61; title_clear# 访问文章并保存文本信息和图片到指定文件夹
for nums in range(20):text_list &#61; []img_url_list &#61; []article_url &#61; start_url &#43; href_list[nums]response_url &#61; requests.get(article_url, headers&#61;header, timeout&#61;1)html_text &#61; response_url.textsoup_article &#61; BeautifulSoup(html_text, &#39;lxml&#39;)print("正在爬取第{}个页面&#xff01;&#xff01;&#xff01;".format(nums &#43; 1))# 获取子页面文本&#xff08;用find_all方法&#xff09;content_article &#61; soup_article.find_all(&#39;div&#39;, attrs&#61;{&#39;class&#39;: &#39;content&#39;})[-1]text &#61; &#39;&#39;for i in content_article:text &#61; text &#43; i.texttext_list.append(text)# 获取子页面图片链接&#xff08;用select方法&#xff09;soup_article_url &#61; content_article.select(&#39;.pgc-img > img&#39;)for url in soup_article_url:img_url_list.append(url[&#39;src&#39;])# 新建多层文件夹file_name &#61; "建筑档案爬虫文件夹" # 文件夹名称path &#61; r&#39;d:/&#39; &#43; file_nameurl_path_file &#61; path &#43; &#39;/&#39; &#43; title_list[nums] &#43; &#39;/&#39; # 拼接文件夹地址if not os.path.exists(url_path_file):os.makedirs(url_path_file)# 保存子页面图片for index, img_url in enumerate(img_url_list):img_rep &#61; requests.get(img_url, headers&#61;header, timeout&#61;5) # 设置超时时间index &#43;&#61; 1 # 每保存图片一次&#xff0c;显示数量&#43;1img_name &#61; title_list[nums] &#43; &#39; 图片&#39; &#43; &#39;{}&#39;.format(index) # 图片名称img_path &#61; url_path_file &#43; img_name &#43; &#39;.png&#39; # 图片地址with open(img_path, &#39;wb&#39;) as f:f.write(img_rep.content) # 以二进制的方式写入f.close()print(&#39;第{}张图片保存成功&#xff0c;保存地址为&#xff1a;&#39;.format(index), img_path)# 保存网页文本txt_name &#61; str(title_list[nums] &#43; &#39; &#39; &#43; author_list[nums] &#43; &#39; &#39; &#43; releasetime_list[nums]) # 文本名称txt_path &#61; url_path_file &#43; &#39;/&#39; &#43; txt_name &#43; &#39;.txt&#39; # 文本地址with open(txt_path, &#39;w&#39;, encoding&#61;&#39;utf-8&#39;) as f:f.write(str(text_list[0]))f.close()print("该页面文本保存成功,文本地址为&#xff1a;", txt_path)print("爬取成功&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;")print(&#39;\n&#39;)# 主页面信息保存
data &#61; pd.DataFrame({&#39;title&#39;: title_list,&#39;author&#39;: author_list,&#39;time&#39;: releasetime_list,&#39;url&#39;: href_list})
data.to_excel(&#39;{}./data.xls&#39;.format(path), index&#61;False)
print(&#39;保存成功,excel文件地址&#xff1a;&#39;, &#39;{}/data.xls&#39;.format(path))print(&#39;爬取完成!!!!&#39;)
end_time &#61; time.time()
print(&#39;爬取所用时长&#xff1a;&#39;, end_time - start_time)



结语

后续有时间再对该案例扩展防反爬措施&#xff08;ip池、表头池、响应访问&#xff09;、数据处理&#xff08;数据分析、数据可视化&#xff09;等内容




参考文章

【爬虫实战案例1】基于Requests&#43;Xpath&#43;Pandas简单实现爬虫需求_inganxu-CSDN博客

【爬虫实战案例1】基于Scrapy&#43;Xpath简单实现爬虫需求_inganxu-CSDN博客_scrapy爬虫案例


推荐阅读
  • 离线环境下的Python及其第三方库安装指南
    在项目开发中,有时会遇到电脑只能连接内网或完全无法联网的情况。本文将详细介绍如何在这种环境下安装Python及其所需的第三方库,确保开发工作的顺利进行。 ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文介绍了在安装或运行 Python 项目时遇到的 'ModuleNotFoundError: No module named setuptools_rust' 错误,并提供了解决方案。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 掌握远程执行Linux脚本和命令的技巧
    本文将详细介绍如何利用Python的Paramiko库实现远程执行Linux脚本和命令,帮助读者快速掌握这一实用技能。通过具体的示例和详尽的解释,让初学者也能轻松上手。 ... [详细]
  • 本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 深入理解Tornado模板系统
    本文详细介绍了Tornado框架中模板系统的使用方法。Tornado自带的轻量级、高效且灵活的模板语言位于tornado.template模块,支持嵌入Python代码片段,帮助开发者快速构建动态网页。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
author-avatar
哭着说再见0
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有