PHP+JS+CSS+JSON 新闻采集系统实现方案
下面是一个完整的实现方案,用于采集中国新闻网(Chinanews.com)的最新新闻,并以JSON格式存储数据,支持翻页和伪静态。
系统架构
/news-collector/
├── index.php // 主控制器
├── functions.php // 核心功能函数
├── config.php // 配置文件
├── static/
│ ├── css/style.css // 样式文件
│ └── js/script.js // JavaScript文件
├── storage/ // JSON存储目录
│ ├── page1.json
│ ├── page2.json
│ └── ...
└── .htaccess // Apache伪静态规则
1. 配置文件 (config.php)
<?php
// 基本配置
define('SITE_URL', 'https://www.chinanews.com/');
define('PER_PAGE', 10); // 每页显示新闻数量
define('MAX_PAGES', 5); // 最大采集页数
define('STORAGE_DIR', __DIR__ . '/storage/');
define('CACHE_TIME', 3600); // 缓存时间1小时
// 确保存储目录存在
if (!file_exists(STORAGE_DIR)) {
mkdir(STORAGE_DIR, 0755, true);
}
2. 核心功能 (functions.php)
<?php
require_once 'config.php';
/**
* 采集中国新闻网新闻
*/
function fetch_news($page = 1) {
$url = SITE_URL . ($page > 1 ? "scroll-news/news{$page}.html" : "scroll-news/news1.html");
$html = file_get_contents($url);
if (!$html) {
return false;
}
// 使用DOMDocument解析HTML
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DOMXPath($dom);
$news = [];
$items = $xpath->query("//div[contains(@class, 'content_list')]//li");
foreach ($items as $item) {
$titleNode = $xpath->query(".//a", $item)->item(0);
if (!$titleNode) continue;
$title = trim($titleNode->nodeValue);
$link = $titleNode->getAttribute('href');
// 处理相对链接
if (strpos($link, 'http') !== 0) {
$link = SITE_URL . ltrim($link, '/');
}
// 获取新闻详情
$content = fetch_news_content($link);
$news[] = [
'title' => $title,
'link' => $link,
'content' => $content,
'time' => date('Y-m-d H:i:s'),
'source' => '中国新闻网'
];
}
return $news;
}
/**
* 获取新闻详情内容
*/
function fetch_news_content($url) {
$html = @file_get_contents($url);
if (!$html) return '';
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DOMXPath($dom);
// 尝试获取正文内容 - 根据中国新闻网的实际结构调整
$content = '';
$paragraphs = $xpath->query("//div[contains(@class, 'left_zw')]//p");
foreach ($paragraphs as $p) {
$content .= '<p>' . trim($p->nodeValue) . '</p>';
}
return $content;
}
/**
* 保存新闻数据到JSON
*/
function save_news_to_json($page, $data) {
$filename = STORAGE_DIR . "page{$page}.json";
file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
return $filename;
}
/**
* 从JSON加载新闻数据
*/
function load_news_from_json($page) {
$filename = STORAGE_DIR . "page{$page}.json";
if (!file_exists($filename)) {
return false;
}
$data = file_get_contents($filename);
return json_decode($data, true);
}
/**
* 检查是否需要更新缓存
*/
function is_cache_expired($page) {
$filename = STORAGE_DIR . "page{$page}.json";
if (!file_exists($filename)) {
return true;
}
return (time() - filemtime($filename)) > CACHE_TIME;
}
3. 主控制器 (index.php)
<?php
require_once 'functions.php';
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
// 检查缓存或采集新数据
if (is_cache_expired($page)) {
$news = fetch_news($page);
if ($news) {
save_news_to_json($page, $news);
} else {
// 采集失败,尝试加载缓存
$news = load_news_from_json($page) ?: [];
}
} else {
$news = load_news_from_json($page) ?: [];
}
// 输出HTML
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>中国新闻网新闻采集 - 第<?php echo $page; ?>页</title>
<link rel="stylesheet" href="static/css/style.css">
</head>
<body>
<div class="container">
<h1>中国新闻网最新新闻</h1>
<div class="news-list" id="newsList">
<?php if (!empty($news)): ?>
<?php foreach ($news as $item): ?>
<div class="news-item">
<h2><a href="<?php echo htmlspecialchars($item['link']); ?>" target="_blank"><?php echo htmlspecialchars($item['title']); ?></a></h2>
<div class="news-content"><?php echo $item['content']; ?></div>
<div class="news-meta">
<span class="source">来源: <?php echo htmlspecialchars($item['source']); ?></span>
<span class="time">时间: <?php echo htmlspecialchars($item['time']); ?></span>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>暂无新闻数据</p>
<?php endif; ?>
</div>
<div class="pagination">
<?php if ($page > 1): ?>
<a href="<?php echo get_page_url($page - 1); ?>" class="prev">上一页</a>
<?php endif; ?>
<?php for ($i = 1; $i <= MAX_PAGES; $i++): ?>
<a href="<?php echo get_page_url($i); ?>" <?php echo $i == $page ? 'class="active"' : ''; ?>><?php echo $i; ?></a>
<?php endfor; ?>
<?php if ($page < MAX_PAGES): ?>
<a href="<?php echo get_page_url($page + 1); ?>" class="next">下一页</a>
<?php endif; ?>
</div>
</div>
<script src="static/js/script.js"></script>
</body>
</html>
4. JavaScript文件 (static/js/script.js)
document.addEventListener('DOMContentLoaded', function() {
// 可以添加一些交互效果
const newsItems = document.querySelectorAll('.news-item');
newsItems.forEach(item => {
item.addEventListener('click', function(e) {
if (e.target.tagName !== 'A') {
this.querySelector('.news-content').classList.toggle('expanded');
}
});
});
// 可以添加AJAX加载功能
/*
document.querySelectorAll('.pagination a').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const page = this.getAttribute('href').split('=')[1];
fetchNews(page);
});
});
function fetchNews(page) {
fetch(`api.php?page=${page}`)
.then(response => response.json())
.then(data => {
renderNews(data);
history.pushState(null, null, `?page=${page}`);
});
}
*/
});
5. CSS样式文件 (static/css/style.css)
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
line-height: 1.6;
color: #333;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #d32f2f;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.news-list {
margin: 20px 0;
}
.news-item {
padding: 15px;
margin-bottom: 20px;
border: 1px solid #eee;
border-radius: 4px;
transition: all 0.3s ease;
}
.news-item:hover {
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
}
.news-item h2 {
margin: 0 0 10px;
font-size: 18px;
}
.news-item h2 a {
color: #333;
text-decoration: none;
}
.news-item h2 a:hover {
color: #d32f2f;
}
.news-content {
max-height: 100px;
overflow: hidden;
transition: max-height 0.5s ease;
}
.news-content.expanded {
max-height: 2000px;
}
.news-content p {
margin: 5px 0;
font-size: 14px;
color: #666;
}
.news-meta {
margin-top: 10px;
font-size: 12px;
color: #999;
}
.news-meta span {
margin-right: 15px;
}
.pagination {
text-align: center;
margin-top: 30px;
}
.pagination a {
display: inline-block;
padding: 5px 12px;
margin: 0 5px;
border: 1px solid #ddd;
text-decoration: none;
color: #333;
border-radius: 3px;
}
.pagination a:hover {
background-color: #f0f0f0;
}
.pagination a.active {
background-color: #d32f2f;
color: white;
border-color: #d32f2f;
}
6. 伪静态配置
Apache (.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
# 确保不是文件或目录
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 新闻分页伪静态
RewriteRule ^news/page/([0-9]+)/?$ index.php?page=$1 [L,QSA]
# 首页重定向
RewriteRule ^$ index.php [L]
</IfModule>
IIS (web.config)
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="News Pagination" stopProcessing="true">
<match url="^news/page/([0-9]+)/?$" />
<action type="Rewrite" url="index.php?page={R:1}" />
</rule>
<rule name="Homepage" stopProcessing="true">
<match url="^$" />
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
宝塔面板伪静态
在宝塔面板中选择网站 -> 设置 -> 伪静态,然后粘贴Apache的.htaccess规则即可。
使用说明
- 将上述文件按照目录结构放置
- 确保服务器支持PHP和URL重写
- 根据实际需要调整中国新闻网的HTML解析逻辑,因为网站结构可能会变化
- 可以通过修改config.php中的配置来调整采集参数
注意事项
- 网站采集应遵守中国新闻网的robots.txt规定
- 频繁采集可能会被限制IP,建议合理设置缓存时间
- 实际应用中应考虑添加错误处理和日志记录
- 网站结构变化时需要相应调整解析逻辑
这个实现方案提供了完整的采集、存储、展示和分页功能,同时支持伪静态URL,适合在IIS和宝塔面板环境中部署。 更多详情:baijiahao.baidu.com/s?id=183050…