作品介绍
作品名称:自动抓取网站文章的工具
用到的库:requests、bs4、urllib.parse、logging、subprocess、os、tempfile
作品简介:该实例用于自动抓取特定网站文章并将其保存为Word文档(.docx)的脚本。它使用了requests
库来获取网页内容,BeautifulSoup
从bs4
库中解析HTML,urljoin
从urllib.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学习资料,里面的内容都是适合零基础小白的笔记和资料,不懂编程也能听懂、看懂。如果需要的话直接划到文末免费获得,让我们一起学习!