目录
前言
1. 导入必要的库
2. 界说获取网页HTML内容的函数 get_html
3. 界说获取数据的函数 get_data
4. 界说获取文章正文内容的函数 content_text
5. 界说获取单条课程数据的函数 get_one_course_data
6. 界说保存数据的函数 `save_data`
7. 界说文件名合法化处理函数 `sanitize_filename`
8. 主步伐
前言
在信息爆炸的时代,互联网已成为数据获取的核心渠道。从学术研究到商业分析,从新闻监控到用户行为洞察,数据的价值日益凸显。而网络爬虫(Web Crawler)作为主动化获取网络数据的核心技能,正扮演着越来越重要的角色。本案例将通过一个完备的 Python 爬虫案例,构建高效、可靠的爬虫体系,实现对中文日报网站内容的主动化抓取与结构化存储。
说明
遵守法律法规:确保爬取的内容符合目标网站的 robots 协议,避免侵犯他人知识产权。
合理控制请求频率:通过time.sleep()等机制低落对目标服务器的压力,防止 IP 被封禁。
动态调解策略:网页结构大概变化,需根据实际情况修改解析逻辑(如 CSS 选择器)。
实战导向:以 中国日报(China Daily) 真实网页为目标,演示从页面解析到数据存储的全流程,代码可直接复用于雷同网站。
技能覆盖:涵盖 HTTP 请求、HTML 解析、反爬策略、数据清洗、文件存储等核心技能,联合requests、BeautifulSoup、pandas等主流库,提拔代码实战能力。
模块化设计:通过函数封装实现功能解耦,低落代码复杂度,便于后续扩展与维护。
反爬与稳定性:包含请求头伪装、异常处理、延时机制等策略,减少被目标网站封禁的风险。
把握 Python 爬虫的根本架构与工作流程;
学会利用BeautifulSoup解析复杂 HTML 结构;
明确并处理网页反爬机制(如请求头伪装、延时控制);
实现数据的清洗、存储与长期化(CSV 文件);
相识图片下载与文件名合法化处理本领。
实用场景
本案例得当以下读者:
对 Python 爬虫感兴趣的初学者;
必要批量获取公开网络数据的开发者;
希望相识新闻聚合、舆情监控等应用的从业者。
代码亮点
智能编码处理:利用chardet主动检测网页编码,避免乱码问题;
结构化数据存储:通过pandas将数据保存为 CSV 文件,便于后续分析;
图片当地化存储:主动下载文章配图并命名,支持特别字符过滤;
分页爬取支持:主动识别 “下一页” 链接,实现无限翻页抓取。
后续扩展建议
添加代理池以应对反爬限定;
集成 Scrapy 框架提拔爬取效率;
增长数据去重与增量更新功能;
联合 NLP 技能对新闻内容进行情感分析。
构建高效的中文日报内容抓取体系
1. 导入必要的库
- import os.path
- import requests
- import chardet
- import time
- from bs4 import BeautifulSoup
- import pandas as pd
- import re
复制代码 os.path:用于处理文件路径相干操作,比方检查文件是否存在
requests:用于发送HTTP请求,获取网页内容
chardet:用于检测网页内容的字符编码
time:用于添加延时,避免对目标网站造成过大压力
BeautifulSoup:用于解析HTML和XML文档,方便提取所需信息
pandas:用于数据处理和保存,将爬取的数据保存为CSV文件
re:用于正则表达式操作,比方文件名的合法化处理
2. 界说获取网页HTML内容的函数 get_html
- def get_html(url):
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0'
- }
- try:
- # 发送请求
- response = requests.get(url, headers=headers)
- # 检查请求响应状态码
- response.raise_for_status()
- # 设置相应内容字符编码
- response.encoding = chardet.detect(response.content)['encoding']
- return response.text
- except Exception as e:
- print(e)
- finally:
- time.sleep(2)
复制代码 功能:发送HTTP请求获取指定URL的网页内容,并处理字符编码
步骤:
1. 设置请求头 `headers`,模仿欣赏器访问,避免被网站识别为爬虫
2. 利用 `requests.get` 方法发送请求
3. 利用 `raise_for_status` 方法检查响应状态码,如果状态码不是200,抛出异常
4. 利用 `chardet` 检测网页内容的字符编码,并设置响应的编码
5. 返回网页的文本内容
6. 无论请求是否成功,最后都利用 `time.sleep(2)` 暂停2秒,避免频繁请求
3. 界说获取数据的函数 get_data
- def get_data(html):
- # 解析HTML文本
- bs = BeautifulSoup(html, 'lxml')
- # 查找第一个符合class_="left-liebiao"条件div的标签
- div_tag_one = bs.find('div', class_="left-liebiao")
- # 查找所有符合class_="busBox3"条件的div标签
- div_tags = div_tag_one.find_all('div', class_="busBox3")
- return [get_one_course_data(div_tag) for div_tag in div_tags]
复制代码 功能:从网页HTML内容中提取所需的数据。
步骤:
1. 利用 `BeautifulSoup` 解析HTML文本
2. 查找第一个 `class` 为 `left-liebiao` 的 `div` 标签
3. 在该 `div` 标签内查找所有 `class` 为 `busBox3` 的 `div` 标签
4. 遍历这些 `div` 标签,调用 `get_one_course_data` 函数提取每条数据
4. 界说获取文章正文内容的函数 content_text
- def content_text(content_url):
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0'
- }
- # 发送请求
- response = requests.get(content_url)
- # 检查请求响应状态码
- response.raise_for_status()
- # 设置相应内容字符编码
- response.encoding = chardet.detect(response.content)['encoding']
- html = response.text
- # 解析HTML文本
- bs = BeautifulSoup(html, 'lxml')
- # 查找所有符合id="Content"条件的div标签
- div = bs.find('div', id="Content")
- p_tags = div.find_all('p')
- # 写入文本
- texts = [texts.text for texts in p_tags]
- texts = ''.join(texts)
- return texts
复制代码 功能:根据文章链接获取文章的正文内容。
步骤:
1. 设置请求头,发送HTTP请求。
2. 检查响应状态码,设置字符编码。
3. 利用 `BeautifulSoup` 解析HTML文本。
4. 查找 `id` 为 `Content` 的 `div` 标签。
5. 在该 `div` 标签内查找所有 `p` 标签。
6. 提取 `p` 标签的文本内容,并拼接成一个字符串返回。
5. 界说获取单条课程数据的函数 get_one_course_data
- def get_one_course_data(div_tag):
- # 找到标题内容
- title_tag = div_tag.select_one('div > div:nth-child(2) > h3 > a')
- title = title_tag.text.strip() if title_tag is not None else None
- # 保存图片
- img_tag = div_tag.select_one('img')
- print(img_tag)
- if img_tag:
- img_url = img_tag.get('src')
- img_url = 'https:' + img_url
- img = requests.get(img_url)
- img.raise_for_status()
- img_name = sanitize_filename(title)
- print(img_name)
- file_name = f'test/{img_name}.jpg'
- with open(file_name, 'wb') as f:
- f.write(img.content)
- # 找到摘要内容
- abstract_tag = div_tag.select_one('div > div:nth-child(2) > p')
- abstract = ''.join([abstracts.strip() for abstracts in abstract_tag if isinstance(abstracts, str)])
- # 找到日期内容
- date_tag = div_tag.select_one('div > div:nth-child(2) > p > b')
- date = date_tag.text.strip() if date_tag is not None else None
- # 爬取正文内容
- content_url = 'https:' + title_tag.get('href')
- content = content_text(content_url)
- return title, abstract, date, content
复制代码 功能:从单个 `div` 标签中提取标题、图片、择要、日期和正文内容。
步骤:
1. 利用 `select_one` 方法找到标题标签,并提取标题文本
2. 找到图片标签,获取图片链接,发送请求下载图片,并保存到当地。利用 `sanitize_filename` 函数对文件名进行合法化处理
3. 找到择要标签,提取择要内容
4. 找到日期标签,提取日期内容
5. 构建文章链接,调用 `content_text` 函数获取文章正文内容
6. 返回标题、择要、日期和正文内容
6. 界说保存数据的函数 `save_data`
- def save_data(data, file_name):
- df = pd.DataFrame(data, columns=['标题', '摘要', '日期', '详情(新闻内容)'])
- if not os.path.exists(file_name):
- df.to_csv(file_name,
- encoding='utf-8-sig', # 编码为utf-8-sig
- header=True, # 添加列名
- index=False) # 不添加行索引
- else:
- df.to_csv(file_name,
- encoding='utf-8-sig', # 编码为utf-8-sig
- header=False, # 不加列名
- index=False, # 不添加行索引
- mode='a') # 追加数据
- return
复制代码 功能:将爬取的数据保存为CSV文件。
步骤:
1. 利用 `pandas` 的 `DataFrame` 方法将数据转换为数据框
2. 检查文件是否存在,如果不存在,则创建文件并添加列名;如果存在,则追加数据,不添加列名
7. 界说文件名合法化处理函数 `sanitize_filename`
- def sanitize_filename(filename):
- # 定义正则表达式,匹配所有不合法的字符
- pattern = r'[\\*?:"<>|【】]'
- # 将不合法的字符替换为下划线
- return re.sub(pattern, '_', filename)
复制代码 功能:将文件名中的不合法字符替换为下划线,避免保存文件时出现错误
8. 主步伐
- if __name__ == '__main__':
- # 爬取地址
- url = f'https://china.chinadaily.com.cn/5bd5639ca3101a87ca8ff636/page_39.html' # 如果改成其它的url,可能有反爬策略和不同的内容定位策略+翻页规则
- while url:
- # 获取网页文本内容
- html = get_html(url)
- if not html:
- break
- # 获取关键信息
- data = get_data(html)
- # 写入文件
- file_name = '中文日报.csv'
- save_data(data, file_name)
- # 解析HTML文本,查找下一页链接
- bs = BeautifulSoup(html, 'lxml')
- next_page_tag = bs.find('a', text='下一页')
- if next_page_tag:
- url = 'https:' + next_page_tag.get('href')
- else:
- url = None
复制代码 功能:从指定URL开始爬取数据,直到没有下一页为止。
步骤:
1. 界说初始爬取URL
2. 利用 `while` 循环,只要 `url` 不为空,就继续爬取
3. 调用 `get_html` 函数获取网页HTML内容
4. 调用 `get_data` 函数提取关键信息
5. 调用 `save_data` 函数将数据保存到CSV文件
6. 解析HTML文本,查找下一页链接。如果找到,则更新 `url`;否则,将 `url` 置为 `None`,结束循环
运行结果:

保存的图片如果没有明确指定文件路径则默认到当前工作目录下,保存的图片:

这个爬虫代码的案例主要功能是从指定的网页开始,爬取新闻标题、择要、日期、正文内容和图片,并将数据保存为CSV文件。代码通过界说多个函数,将不同的功能模块化,进步了代码的可读性和可维护性。通过添加了异常处理和延时机制,避免对目标网站造成过大压力。完备代码:
- import os.path
- import requests
- import chardet
- import time
- from bs4 import BeautifulSoup
- import pandas as pd
- import re
- def get_html(url): headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0' } try: # 发送请求 response = requests.get(url,headers=headers) # 检查请求响应状态码 response.raise_for_status() # 设置相应内容字符编码 response.encoding = chardet.detect(response.content)['encoding'] return response.text except Exception as e: print(e) finally: time.sleep(2)def get_data(html): # 解析HTML文本 bs = BeautifulSoup(html,'lxml') # 查找第一个符合class_="left-liebiao"条件div的标签 div_tag_one = bs.find('div',class_="left-liebiao") # 查找所有符合class_="busBox3"条件的div标签 div_tags = div_tag_one.find_all('div',class_="busBox3") return [get_one_course_data(div_tag) for div_tag in div_tags]def content_text(content_url): headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0' } # 发送请求 response = requests.get(content_url) # 检查请求响应状态码 response.raise_for_status() # 设置相应内容字符编码 response.encoding = chardet.detect(response.content)['encoding'] html = response.text # 解析HTML文本 bs = BeautifulSoup(html, 'lxml') # 查找所有符合id="Content"条件的div标签 div = bs.find('div', id="Content") p_tags = div.find_all('p') # 写入文本 texts = [texts.text for texts in p_tags] texts = ''.join(texts) return textsdef get_one_course_data(div_tag): # 找到标题内容 title_tag = div_tag.select_one('div > div:nth-child(2) > h3 > a') title = title_tag.text.strip() if title_tag is not None else None # 保存图片 img_tag = div_tag.select_one('img') print(img_tag) if img_tag: img_url = img_tag.get('src') img_url = 'https:' + img_url img = requests.get(img_url) img.raise_for_status() img_name = sanitize_filename(title) print(img_name) file_name = f'test/{img_name}.jpg' with open(file_name, 'wb') as f: f.write(img.content) # 找到择要内容 abstract_tag = div_tag.select_one('div > div:nth-child(2) > p') abstract = ''.join([abstracts.strip() for abstracts in abstract_tag if isinstance(abstracts, str)]) # 找到日期内容 date_tag = div_tag.select_one('div > div:nth-child(2) > p > b') date = date_tag.text.strip() if date_tag is not None else None # 爬取正文内容 content_url = 'https:' + title_tag.get('href') content = content_text(content_url) return title,abstract,date,contentdef save_data(data,file_name): df = pd.DataFrame(data,columns=['标题','择要','日期','详情(新闻内容)']) if not os.path.exists(file_name): df.to_csv(file_name, encoding='utf-8-sig', # 编码为utf-8-sig header=True, # 添加列名 index=False) # 不添加行索引 else: df.to_csv(file_name, encoding='utf-8-sig', # 编码为utf-8-sig header=False, # 不加列名 index=False, # 不添加行索引 mode='a') # 追加数据 returndef sanitize_filename(filename):
- # 定义正则表达式,匹配所有不合法的字符
- pattern = r'[\\*?:"<>|【】]'
- # 将不合法的字符替换为下划线
- return re.sub(pattern, '_', filename)
- if __name__=='__main__': # 爬取地点 url = f'https://china.chinadaily.com.cn/5bd5639ca3101a87ca8ff636/page_39.html' # 如果改成其它的url,大概有反爬策略和不同的内容定位策略+翻页规则 while url: # 获取网页文本内容 html = get_html(url) if not html: break # 获取关键信息 data = get_data(html) # 写入文件 file_name = '中文日报.csv' save_data(data, file_name) # 解析HTML文本,查找下一页链接 bs = BeautifulSoup(html,'lxml') next_page_tag = bs.find('a',text='下一页') if next_page_tag: url = 'https:' + next_page_tag.get('href') else: url = None
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |