python自动化系列:自动抓取网站文章的工具

作品介绍

作品名称:自动抓取网站文章的工具

用到的库:requests、bs4、urllib.parse、logging、subprocess、os、tempfile

作品简介:该实例用于自动抓取特定网站文章并将其保存为Word文档(.docx)的脚本。它使用了requests库来获取网页内容,BeautifulSoupbs4库中解析HTML,urljoinurllib.parse模块中构建完整的URL,以及pandoc通过subprocess调用来转换HTML到Word文档。

请注意,这个脚本假设目标网站的HTML结构是固定的,并且文章内容存放在特定的HTML标签内。如果网站的结构发生变化,或者需要处理JavaScript渲染的内容,那么这个脚本可能需要相应的调整。此外,对于大规模或频繁的数据抓取操作,请确保遵守目标网站的使用条款和robots.txt规则,以免违反网站政策。

实现过程

一、导入必要的库


import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import logging
import subprocess
import os
from tempfile import NamedTemporaryFile

二、初始化

  • 设置日志记录格式以跟踪脚本的执行情况。

  • 定义了两个URL:一个是基础URL(BASE_URL),另一个是包含文章列表的页面URL(ARTICLES_URL)。


# 设置日志格式
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

BASE_URL = "https://youzhiyouxing.cn"
ARTICLES_URL = f"{BASE_URL}/topics/ezone/nodes/2"

三、获取网页内```容 (fetch_page`)``

  • 使用requests.get方法请求指定的URL,并检查响应状态码。

  • 如果请求成功,则返回网页的内容;否则,记录错误信息并返回None。


def fetch_page(url):
    """获取网页内容"""
    try:
        response = requests.get(url)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        logging.error(f"Failed to fetch {url}: {e}")
        return None
四、解析文章链接 (parse_article_links)
  • 使用BeautifulSoup解析获取到的HTML内容,选择特定的选择器来查找文章链接。

  • 构建每个文章的完整URL,并将它们添加到列表中返回。


def parse_article_links(html_content):
    """解析文章链接"""
    soup = BeautifulSoup(html_content, 'lxml')
    article_links = []

    for a in soup.select('ul.materials a.tw-text-t-normal'):
        href = a.get('href')
        if href:
            full_url = urljoin(BASE_URL, href)
            article_links.append(full_url)

    return article_links

五、解析单篇文章内容 (parse_article_content)

  • 通过fetch_page函数获取单个文章的HTML内容。

  • 使用BeautifulSoup解析HTML,找到包含文章内容的容器。

  • 提取标题和内容,并作为字典返回。


def parse_article_content(article_url):
    """解析单篇文章的内容"""
    html_content = fetch_page(article_url)
    if not html_content:
        return None

    soup = BeautifulSoup(html_content, 'lxml')

    # 获取整个页面的HTML片段(假设文章在特定的容器内)
    container = soup.select_one('div.markdown-container')  # 根据实际情况调整选择器
    if not container:
        logging.warning("No markdown-container found.")
        return {'title': 'No Title', 'content': 'No Content'}

    title = container.find_previous('h2').get_text(strip=True) if container.find_previous('h2') else 'No Title'

    return {'title': title, 'content': str(container)}

六、保存到Word文档 (save_to_word_with_pandoc)

  • 创建一个临时HTML文件,将所有文章的标题和内容写入该文件。

  • 使用pandoc命令行工具将HTML文件转换为Word文档,尽量保留原始格式。

  • 删除临时创建的HTML文件。


def save_to_word_with_pandoc(articles_data, filename='articles_normal.docx'):
    """将文章数据保存到Word文档,并尽量保留格式"""
    with NamedTemporaryFile(mode='w+', suffix='.html', delete=False, encoding='utf-8') as temp_html_file:
        for idx, article in enumerate(articles_data, start=1):
            temp_html_file.write(f"

Article {idx}: {article['title']}

\n") temp_html_file.write(article['content']) temp_html_file.write('
\n') # 分割线 temp_html_filename = temp_html_file.name try: # 使用 pandoc 将 HTML 转换为 DOCX,确保使用 UTF-8 编码 subprocess.run(['pandoc', '--from=html', '--to=docx', '--output=' + filename, temp_html_filename], check=True) logging.info(f"Saved articles to {filename} with formatting preserved.") except subprocess.CalledProcessError as e: logging.error(f"Pandoc failed to convert HTML to DOCX: {e}") finally: # 删除临时文件 os.unlink(temp_html_filename)

七、主逻辑 (main)

  • 获取文章列表页的HTML内容。

  • 解析出所有文章的链接。

  • 对于每个文章链接,获取其内容并存储在一个列表中。

  • 将所有文章的数据保存到一个Word文档中。


def main():
    logging.info("Fetching articles list page...")
    articles_html = fetch_page(ARTICLES_URL)
    if not articles_html:
        logging.error("Failed to fetch articles list page.")
        return

    logging.info("Parsing article links...")
    article_links = parse_article_links(articles_html)
    if not article_links:
        logging.warning("No article links found.")
        return

    articles_data = []
    for idx, link in enumerate(article_links, start=1):
        logging.info(f"Fetching article {idx}/{len(article_links)}: {link}")
        article_data = parse_article_content(link)
        if article_data:
            articles_data.append(article_data)
        else:
            logging.error(f"Failed to fetch article content from {link}")

    if articles_data:
        save_to_word_with_pandoc(articles_data)
    else:
        logging.warning("No articles data to save.")

八、入口点

  • 当脚本被直接运行时,会调用main函数开始执行抓取和保存过程。
if __name__ == "__main__":`    `main()

九、结语

以上就是本次分享的全部内容,如果你有任何疑问或想要分享你的自动化办公经验,我们的评论区永远为你敞开。你的每一个点赞和转发,都是对我们最大的支持和鼓励!

 希望这篇文章对正在学习编程的你有所帮助,如果你想学习编程,那给大家分享一份Python学习资料,里面的内容都是适合零基础小白的笔记和资料,不懂编程也能听懂、看懂。如果需要的话直接划到文末免费获得,让我们一起学习!

在这里插入图片描述

python自动化系列:自动抓取网站文章的工具_第1张图片

你可能感兴趣的:(零基础教程,Python教程,Python,python,自动化,开发语言)