前言
分享一篇使用部分爬虫技术简单实现对媒体类网页按需求爬取文章并保存到本地指定文件夹的案例,仅供相关学习者参考,学习过程切勿对网站频繁访问而造成网页瘫痪,量力而为!!!
BeautifulSoup的简单使用:https://inganxu.blog.csdn.net/article/details/122783587
爬取需求
爬取地址:建筑档案-建筑行业全产业链内容共建平台
爬取涉及技术:Requests(访问)、BeautifulSoup、Re(解析)、Pandas(保存)
爬取目的:仅用于练习巩固爬虫技术
爬取目标:
- 将网页首页中每个文章的标题、作者、发布时间、文章链接保存到指定位置的excel文件中,excel名称为data
- 将每个文章的文本保存到指定位置的文档中,并以文章标题命名
- 将每个文章的图片保存到指定位置的文件夹中,并以文章标题 + 图片序号命名
爬取思路
发起首页网页请求,获取响应内容
解析首页网页数据,获取文章的标题、作者、发布时间、文章链接信息
汇总网站首页信息,保存到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('p', attrs={'class': 'name'}):
if len(author_list) < 20:
author = re.findall(r'(?<=\s)\D+(?=\s\.)', author_time.text)[0]
author_list.append(author.replace(' ', ''))
if len(releasetime_list) < 20:
time = re.findall(r'\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}', author_time.text)
releasetime_list.append(time[0])
解析过程发现获取的内容头部或尾部有不需要的信息,因此使用列表切片方式将元素剔除掉
步骤四:数据清洗
# 主页面数据清洗
author_clear = []
for i in author_list:
if i != '.':
author_clear.append(i.replace('\n', '').replace(' ', ''))
author_list = author_clear
time_clear = []
for j in releasetime_list:
time_clear.append(j.replace('\n', '').replace(' ', '').replace(':', ''))
releasetime_list = time_clear
title_clear = []
for n in title_list:
title_clear.append(
n.replace(':', ' ').replace('!', ' ').replace('|', ' ').replace('/', ' ').replace(' ', ' '))
title_list = title_clear
查看网页结构,可以看到标题、作者、发布时间都有一些系统敏感字符(影响后续无法创建文件夹)
所以,需要把解析到的数据作数据清洗后才能使用
步骤五:访问文章链接并解析提取响应内容
通过对比网页结构的@href属性链接和文章的真实链接,可知解析到的url需要拼接网址首页进去
# 访问文章并保存文本信息和图片到指定文件夹
for nums in range(20):
text_list = []
img_url_list = []
article_url = start_url + href_list[nums]
response_url = requests.get(article_url, headers=header, timeout=1)
html_text = response_url.text
soup_article = BeautifulSoup(html_text, 'lxml')
# 获取子页面文本(用find_all方法)
content_article = soup_article.find_all('div', attrs={'class': 'content'})[-1]
text = ''
for i in content_article:
text = text + i.text
text_list.append(text)
# 获取子页面图片链接(用select方法)
soup_article_url = content_article.select('.pgc-img > img')
for url in soup_article_url:
img_url_list.append(url['src'])
拼接文本内容是因为获取到的文本信息是一段一段分开的,需要拼接在一起,才是完整的文章文本信息
步骤六:创建多层文件夹
新建多层文件夹
file_name = "建筑档案爬虫文件夹" # 文件夹名称
path = r'd:/' + file_name
url_path_file = path + '/' + title_list[nums] + '/' # 拼接文件夹地址
if not os.path.exists(url_path_file):
os.makedirs(url_path_file)
因为创建的文件夹是:“./爬虫文件夹名称/文章标题名称/”,所以需要用os.makedirs来创建多层文件夹
注意文件名称最后带 “/”
步骤七:保存子页面图片
当建立好文件夹后,就开始访问每个文章的图片链接,并且保存下来
# 保存子页面图片
for index, img_url in enumerate(img_url_list):
img_rep = requests.get(img_url, headers=header, timeout=5) # 设置超时时间
index += 1 # 每保存图片一次,显示数量+1
img_name = title_list[nums] + ' 图片' + '{}'.format(index) # 图片名称
img_path = url_path_file + img_name + '.png' # 图片地址
with open(img_path, 'wb') as f:
f.write(img_rep.content) # 以二进制的方式写入
f.close()
步骤八:保存子页面文本
先保存文本再保存图片也可以,需要注意两者的写入方式
# 保存网页文本
txt_name = str(title_list[nums] + ' ' + author_list[nums] + ' ' + releasetime_list[nums]) # 文本名称
txt_path = url_path_file + '/' + txt_name + '.txt' # 文本地址
with open(txt_path, 'w', encoding='utf-8') as f:
f.write(str(text_list[0]))
f.close()
步骤九:文章信息汇总
将网站首页的所有文章标题、作者、发布时间、文章链接都保存到一个excel文件夹中
# 主页面信息保存
data = pd.DataFrame({'title': title_list,
'author': author_list,
'time': releasetime_list,
'url': href_list})
data.to_excel('{}./data.xls'.format(path), index=False)
完整代码(面向过程版)
# !/usr/bin/python3.9
# -*- coding:utf-8 -*-
# @author:inganxu
# CSDN:inganxu.blog.csdn.net
# @Date:2022年2月3日
import requests # 用于发起网页请求,返回响应内容
import pandas as pd # 生成二维数据,保存到excel中
import os # 文件保存
import time # 减慢爬虫速度
import re # 提取解析内容
from bs4 import BeautifulSoup # 对响应内容解析数据
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'}
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('p', attrs={'class': 'name'}):
if len(author_list) < 20:
author = re.findall(r'(?<=\s)\D+(?=\s\.)', author_time.text)[0]
author_list.append(author.replace(' ', ''))
if len(releasetime_list) < 20:
time = re.findall(r'\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}', author_time.text)
releasetime_list.append(time[0])
# 主页面数据清洗
author_clear = []
for i in author_list:
if i != '.':
author_clear.append(i.replace('\n', '').replace(' ', ''))
author_list = author_clear
time_clear = []
for j in releasetime_list:
time_clear.append(j.replace('\n', '').replace(' ', '').replace(':', ''))
releasetime_list = time_clear
title_clear = []
for n in title_list:
title_clear.append(
n.replace(':', ' ').replace('!', ' ').replace('|', ' ').replace('/', ' ').replace(' ', ' '))
title_list = title_clear
# 访问文章并保存文本信息和图片到指定文件夹
for nums in range(20):
text_list = []
img_url_list = []
article_url = start_url + href_list[nums]
response_url = requests.get(article_url, headers=header, timeout=1)
html_text = response_url.text
soup_article = BeautifulSoup(html_text, 'lxml')
print("正在爬取第{}个页面!!!".format(nums + 1))
# 获取子页面文本(用find_all方法)
content_article = soup_article.find_all('div', attrs={'class': 'content'})[-1]
text = ''
for i in content_article:
text = text + i.text
text_list.append(text)
# 获取子页面图片链接(用select方法)
soup_article_url = content_article.select('.pgc-img > img')
for url in soup_article_url:
img_url_list.append(url['src'])
# 新建多层文件夹
file_name = "建筑档案爬虫文件夹" # 文件夹名称
path = r'd:/' + file_name
url_path_file = path + '/' + title_list[nums] + '/' # 拼接文件夹地址
if not os.path.exists(url_path_file):
os.makedirs(url_path_file)
# 保存子页面图片
for index, img_url in enumerate(img_url_list):
img_rep = requests.get(img_url, headers=header, timeout=5) # 设置超时时间
index += 1 # 每保存图片一次,显示数量+1
img_name = title_list[nums] + ' 图片' + '{}'.format(index) # 图片名称
img_path = url_path_file + img_name + '.png' # 图片地址
with open(img_path, 'wb') as f:
f.write(img_rep.content) # 以二进制的方式写入
f.close()
print('第{}张图片保存成功,保存地址为:'.format(index), img_path)
# 保存网页文本
txt_name = str(title_list[nums] + ' ' + author_list[nums] + ' ' + releasetime_list[nums]) # 文本名称
txt_path = url_path_file + '/' + txt_name + '.txt' # 文本地址
with open(txt_path, 'w', encoding='utf-8') as f:
f.write(str(text_list[0]))
f.close()
print("该页面文本保存成功,文本地址为:", txt_path)
print("爬取成功!!!!!!!!!!!!!!!!!!!!!!!!")
print('\n')
# 主页面信息保存
data = pd.DataFrame({'title': title_list,
'author': author_list,
'time': releasetime_list,
'url': href_list})
data.to_excel('{}./data.xls'.format(path), index=False)
print('保存成功,excel文件地址:', '{}/data.xls'.format(path))
print('爬取完成!!!!')
end_time = time.time()
print('爬取所用时长:', end_time - start_time)
结语
后续有时间再对该案例扩展防反爬措施(ip池、表头池、响应访问)、数据处理(数据分析、数据可视化)等内容