使用Python爬取Chinadaily新闻内容:详解爬虫库函数安装与操作

一、爬取的内容及模块

本文选择爬取chinadaily官网中Home-China-National affairs中的内容

chinadaily官网China Daily Website – Connecting China Connecting the World

爬取的模块:

二、找到所要爬取的新闻的位置

在网页中右击选择检查

找到我们要爬的标题的位置

可以选择滑动鼠标来查看标题具体在哪个位置,如果滑动鼠标没有图中的蓝色显示的话可以选择右边检查上面第一行第一个图标

可以看到我们要爬取的标题都位于h4下面,并且可以找到我们的并列新闻内容都位于

<div class="mb10 tw3_01_2">中

三、要准备的库函数

所需库及其功能

1. requests:用于发送HTTP请求,获取网页内容。
2.beautifulsoup4:用于解析HTML和XML文档,从网页中提取所需的数据。
3.pandas:用于数据处理和分析,这里用来将爬取的数据保存为Excel文件。
4.tqdm:用于在循环中显示进度条,让你了解爬取的进度。
5.openpyxl:pandas保存 Excel文件时使用的引擎。

 

下载库函数以及对PyCharm中进行库的配置

下载库函数:

打开命令行:在电脑下面搜索栏搜索cmd

或者按住win+R,选中或输入cmd

输入命令

pip install requests beautifulsoup4 pandas tqdm openpyxl

总共五个库函数,也可以分个下载

pip install requests
pip install beautifulsoup4 
pip install pandas 
pip install tqdm 
pip install openpyxl

配置库函数:

在PyCharm中选择 文件-设置

在你的项目中选择Python解释器,然后点击右边的加号+

分别搜索我们刚刚需要安装的5个库函数,然后点击下方的安装软件

安装成功后底部会有显示,5个函数的操作方法相同,自行完成5个函数的配置

四、代码段

以下是我本次爬取的代码,爬取的文件存在chinadaily.xlsx的Excel文件中

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
from urllib.parse import urljoin
from tqdm import tqdm
import os

# 基础配置
# 定义爬取的基础URL,此为中国日报政府与政策板块的链接
BASE_URL = 'https://www.chinadaily.com.cn/china/governmentandpolicy'
# 定义请求头,模拟浏览器访问,避免被网站识别为爬虫而拒绝访问
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
    'Accept-Encoding': 'gzip, deflate'
}
# 定义输出文件的名称,爬取到的所有数据将保存到这个Excel文件中
OUTPUT_FILE = 'chinadaily.xlsx'


def smart_crawler():
    """智能全量爬虫(单文件存储版)"""
    # 创建一个会话对象,用于保持连接和管理请求头
    session = requests.Session()
    # 更新会话的请求头
    session.headers.update(HEADERS)
    # 用于存储所有爬取到的文章信息
    all_articles = []
    # 初始化页码为1
    page_num = 1
    # 标记是否有下一页,初始为True
    has_next_page = True
    # 初始化重试次数为0
    retry_count = 0
    # 定义最大重试次数
    MAX_RETRIES = 3

    # 初始化Excel文件(如果存在则先删除)
    if os.path.exists(OUTPUT_FILE):
        os.remove(OUTPUT_FILE)

    # 使用tqdm创建一个进度条,用于显示爬取进度
    with tqdm(desc="爬取进度") as pbar:
        # 当有下一页且重试次数小于最大重试次数时,继续循环
        while has_next_page and retry_count < MAX_RETRIES:
            try:
                # 1. 构建当前页URL
                # 如果页码大于1,构建带页码的URL,否则使用基础URL
                current_url = f"{BASE_URL}/page_{page_num}.html" if page_num > 1 else BASE_URL

                # 2. 获取页面内容
                # 发送GET请求获取当前页的内容,设置超时时间为15秒
                resp = session.get(current_url, timeout=15)
                # 检查请求是否成功,如果不成功则抛出异常
                resp.raise_for_status()
                # 使用BeautifulSoup解析页面内容,使用lxml解析器
                soup = BeautifulSoup(resp.text, 'lxml')

                # 3. 检测是否有效页面
                # 选择所有符合条件的文章元素
                articles = soup.select('div.mb10.tw3_01_2, div[class*="tw3_01_2"]')
                if not articles:
                    # 如果未找到文章,可能已到末页,打印提示信息
                    print(f"⚠️ 第 {page_num} 页未找到文章,可能已到末页")
                    # 重试次数加1
                    retry_count += 1
                    # 暂停2秒
                    time.sleep(2)
                    continue

                # 4. 解析当前页文章
                # 用于存储当前页的文章信息
                page_articles = []
                for item in articles:
                    try:
                        # 提取文章标题
                        title = item.select_one('h4 a, h3 a').get_text(strip=True)
                        # 提取文章链接,并将其转换为绝对URL
                        link = urljoin(BASE_URL, item.select_one('a')['href'])
                        # 提取文章发布时间
                        date = item.select_one('b, span.date').get_text(strip=True)

                        # 获取文章详情
                        # 随机暂停一段时间,避免给服务器造成过大压力
                        time.sleep(random.uniform(0.5, 1.5))
                        # 调用get_article_content函数获取文章内容
                        content = get_article_content(link, session)

                        # 将文章信息添加到当前页文章列表中
                        page_articles.append({
                            '标题': title,
                            '发布时间': date,
                            '新闻内容': content,
                            '来源链接': link,
                            '页码': page_num
                        })
                    except Exception as e:
                        # 如果文章解析失败,打印错误信息
                        print(f"❌ 文章解析失败: {e}")
                        continue

                # 5. 追加到总列表并保存到文件
                # 将当前页的文章信息添加到总文章列表中
                all_articles.extend(page_articles)

                # 实时保存到同一个Excel文件
                # 调用save_to_excel函数将数据保存到Excel文件中
                save_to_excel(all_articles, OUTPUT_FILE)

                # 更新进度条
                pbar.update(len(page_articles))
                # 设置进度条的后缀信息,显示当前页码和总文章数量
                pbar.set_postfix_str(f"当前页: {page_num} | 总量: {len(all_articles)}")

                # 6. 检查是否有下一页
                # 选择下一页的链接元素
                next_page = soup.select_one('a.pagestyle[href*="page_"]')
                # 判断是否有下一页
                has_next_page = bool(next_page)
                # 页码加1
                page_num += 1
                # 重置重试计数器
                retry_count = 0

                # 7. 页间延迟
                # 随机暂停一段时间,避免给服务器造成过大压力
                time.sleep(random.uniform(1, 3))

            except Exception as e:
                # 如果当前页爬取失败,打印错误信息
                print(f"❌ 第 {page_num} 页爬取失败: {e}")
                # 重试次数加1
                retry_count += 1
                # 暂停5秒
                time.sleep(5)

    # 打印爬取完成信息
    print(f"✅ 爬取完成!共获取 {len(all_articles)} 条新闻,已保存到 {OUTPUT_FILE}")


def get_article_content(url, session):
    """获取单篇文章内容"""
    try:
        # 发送GET请求获取文章内容,设置超时时间为10秒
        resp = session.get(url, timeout=10)
        # 使用BeautifulSoup解析文章内容,使用lxml解析器
        soup = BeautifulSoup(resp.text, 'lxml')
        # 选择文章内容元素
        content = soup.select_one('div#Content, div.article')
        # 如果找到文章内容元素,返回其文本内容,否则返回“无正文内容”
        return content.get_text('\n').strip() if content else "无正文内容"
    except:
        # 如果获取文章内容失败,返回“内容获取失败”
        return "内容获取失败"


def save_to_excel(data, filename):
    """保存数据到Excel(自动覆盖模式)"""
    try:
        # 创建DataFrame并排序(按页码)
        # 将数据转换为DataFrame对象,并按页码排序
        df = pd.DataFrame(data).sort_values('页码')

        # 保存到Excel(每次都是全量覆盖)
        # 使用openpyxl引擎创建Excel写入器
        with pd.ExcelWriter(filename, engine='openpyxl') as writer:
            # 将DataFrame写入Excel文件,不保存索引
            df.to_excel(writer, index=False)

            # 调整列宽
            # 获取工作表对象
            worksheet = writer.sheets['Sheet1']
            # 设置标题列的宽度为50
            worksheet.column_dimensions['A'].width = 50
            # 设置时间列的宽度为20
            worksheet.column_dimensions['B'].width = 20
            # 设置内容列的宽度为80
            worksheet.column_dimensions['C'].width = 80
            # 设置链接列的宽度为40
            worksheet.column_dimensions['D'].width = 40
            # 设置页码列的宽度为10
            worksheet.column_dimensions['E'].width = 10
    except Exception as e:
        # 如果保存文件时出错,打印错误信息
        print(f"⚠️ 保存文件时出错: {e}")


if __name__ == '__main__':
    # 调用智能爬虫函数开始爬取数据
    smart_crawler()

五、查看爬取的结果

爬取后的代码我们以及存在文件相同目录下的chinadaily.xlsx中

打开Excel查看

六、注意事项

因为目前该栏下有505页,每页也大约有20条新闻,总计可达一万条左右,爬取的时间可能需要达到5~6个小时,在此期间要保证网络的通畅。

 

作者:X-YX.Y

物联沃分享整理
物联沃-IOTWORD物联网 » 使用Python爬取Chinadaily新闻内容:详解爬虫库函数安装与操作

发表回复