爬虫入门re+bs4

打印 上一主题 下一主题

主题 927|帖子 927|积分 2781

目录
  前言
  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. 导入必要的库

  1. import os.path
  2. import requests
  3. import chardet
  4. import time
  5. from bs4 import BeautifulSoup
  6. import pandas as pd
  7. import re
复制代码
os.path:用于处理文件路径相干操作,比方检查文件是否存在
  requests:用于发送HTTP请求,获取网页内容
  chardet:用于检测网页内容的字符编码
  time:用于添加延时,避免对目标网站造成过大压力
  BeautifulSoup:用于解析HTML和XML文档,方便提取所需信息
  pandas:用于数据处理和保存,将爬取的数据保存为CSV文件
  re:用于正则表达式操作,比方文件名的合法化处理
  
  2. 界说获取网页HTML内容的函数 get_html

  1. def get_html(url):
  2.     headers = {
  3.         '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'
  4.     }
  5.     try:
  6.         # 发送请求
  7.         response = requests.get(url, headers=headers)
  8.         # 检查请求响应状态码
  9.         response.raise_for_status()
  10.         # 设置相应内容字符编码
  11.         response.encoding = chardet.detect(response.content)['encoding']
  12.         return response.text
  13.     except Exception as e:
  14.         print(e)
  15.     finally:
  16.         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

  1. def get_data(html):
  2.     # 解析HTML文本
  3.     bs = BeautifulSoup(html, 'lxml')
  4.     # 查找第一个符合class_="left-liebiao"条件div的标签
  5.     div_tag_one = bs.find('div', class_="left-liebiao")
  6.     # 查找所有符合class_="busBox3"条件的div标签
  7.     div_tags = div_tag_one.find_all('div', class_="busBox3")
  8.     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

  1. def content_text(content_url):
  2.     headers = {
  3.         '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'
  4.     }
  5.     # 发送请求
  6.     response = requests.get(content_url)
  7.     # 检查请求响应状态码
  8.     response.raise_for_status()
  9.     # 设置相应内容字符编码
  10.     response.encoding = chardet.detect(response.content)['encoding']
  11.     html = response.text
  12.     # 解析HTML文本
  13.     bs = BeautifulSoup(html, 'lxml')
  14.     # 查找所有符合id="Content"条件的div标签
  15.     div = bs.find('div', id="Content")
  16.     p_tags = div.find_all('p')
  17.     # 写入文本
  18.     texts = [texts.text for texts in p_tags]
  19.     texts = ''.join(texts)
  20.     return texts
复制代码
功能:根据文章链接获取文章的正文内容。
  步骤:
  1. 设置请求头,发送HTTP请求。
  2. 检查响应状态码,设置字符编码。
  3. 利用 `BeautifulSoup` 解析HTML文本。
  4. 查找 `id` 为 `Content` 的 `div` 标签。
  5. 在该 `div` 标签内查找所有 `p` 标签。
  6. 提取 `p` 标签的文本内容,并拼接成一个字符串返回。
  
  5. 界说获取单条课程数据的函数 get_one_course_data

  1. def get_one_course_data(div_tag):
  2.     # 找到标题内容
  3.     title_tag = div_tag.select_one('div > div:nth-child(2) > h3 > a')
  4.     title = title_tag.text.strip() if title_tag is not None else None
  5.     # 保存图片
  6.     img_tag = div_tag.select_one('img')
  7.     print(img_tag)
  8.     if img_tag:
  9.         img_url = img_tag.get('src')
  10.         img_url = 'https:' + img_url
  11.         img = requests.get(img_url)
  12.         img.raise_for_status()
  13.         img_name = sanitize_filename(title)
  14.         print(img_name)
  15.         file_name = f'test/{img_name}.jpg'
  16.         with open(file_name, 'wb') as f:
  17.             f.write(img.content)
  18.     # 找到摘要内容
  19.     abstract_tag = div_tag.select_one('div > div:nth-child(2) > p')
  20.     abstract = ''.join([abstracts.strip() for abstracts in abstract_tag if isinstance(abstracts, str)])
  21.     # 找到日期内容
  22.     date_tag = div_tag.select_one('div > div:nth-child(2) > p > b')
  23.     date = date_tag.text.strip() if date_tag is not None else None
  24.     # 爬取正文内容
  25.     content_url = 'https:' + title_tag.get('href')
  26.     content = content_text(content_url)
  27.     return title, abstract, date, content
复制代码
功能:从单个 `div` 标签中提取标题、图片、择要、日期和正文内容。
  步骤:
  1. 利用 `select_one` 方法找到标题标签,并提取标题文本
  2. 找到图片标签,获取图片链接,发送请求下载图片,并保存到当地。利用 `sanitize_filename` 函数对文件名进行合法化处理
  3. 找到择要标签,提取择要内容
  4. 找到日期标签,提取日期内容
  5. 构建文章链接,调用 `content_text` 函数获取文章正文内容
  6. 返回标题、择要、日期和正文内容
  
  6. 界说保存数据的函数 `save_data`

  1. def save_data(data, file_name):
  2.     df = pd.DataFrame(data, columns=['标题', '摘要', '日期', '详情(新闻内容)'])
  3.     if not os.path.exists(file_name):
  4.         df.to_csv(file_name,
  5.                   encoding='utf-8-sig',  # 编码为utf-8-sig
  6.                   header=True,  # 添加列名
  7.                   index=False)  # 不添加行索引
  8.     else:
  9.         df.to_csv(file_name,
  10.                   encoding='utf-8-sig',  # 编码为utf-8-sig
  11.                   header=False,  # 不加列名
  12.                   index=False,  # 不添加行索引
  13.                   mode='a')  # 追加数据
  14.     return
复制代码
功能:将爬取的数据保存为CSV文件。
  步骤:
  1. 利用 `pandas` 的 `DataFrame` 方法将数据转换为数据框
  2. 检查文件是否存在,如果不存在,则创建文件并添加列名;如果存在,则追加数据,不添加列名
  
  7. 界说文件名合法化处理函数 `sanitize_filename`

  1. def sanitize_filename(filename):
  2.     # 定义正则表达式,匹配所有不合法的字符
  3.     pattern = r'[\\*?:"<>|【】]'
  4.     # 将不合法的字符替换为下划线
  5.     return re.sub(pattern, '_', filename)
复制代码
功能:将文件名中的不合法字符替换为下划线,避免保存文件时出现错误
  
  8. 主步伐

  1. if __name__ == '__main__':
  2.     # 爬取地址
  3.     url = f'https://china.chinadaily.com.cn/5bd5639ca3101a87ca8ff636/page_39.html'  # 如果改成其它的url,可能有反爬策略和不同的内容定位策略+翻页规则
  4.     while url:
  5.         # 获取网页文本内容
  6.         html = get_html(url)
  7.         if not html:
  8.             break
  9.         # 获取关键信息
  10.         data = get_data(html)
  11.         # 写入文件
  12.         file_name = '中文日报.csv'
  13.         save_data(data, file_name)
  14.         # 解析HTML文本,查找下一页链接
  15.         bs = BeautifulSoup(html, 'lxml')
  16.         next_page_tag = bs.find('a', text='下一页')
  17.         if next_page_tag:
  18.             url = 'https:' + next_page_tag.get('href')
  19.         else:
  20.             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文件。代码通过界说多个函数,将不同的功能模块化,进步了代码的可读性和可维护性。通过添加了异常处理和延时机制,避免对目标网站造成过大压力。完备代码:
  1. import os.path
  2. import requests
  3. import chardet
  4. import time
  5. from bs4 import BeautifulSoup
  6. import pandas as pd
  7. import re
  8. 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):
  9.     # 定义正则表达式,匹配所有不合法的字符
  10.     pattern = r'[\\*?:"<>|【】]'
  11.     # 将不合法的字符替换为下划线
  12.     return re.sub(pattern, '_', filename)
  13. 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企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表