PHP+HTML5+JS+CSS实现新闻自动采集并发布到emlog博客系统
下面我将介绍一个完整的解决方案,使用PHP采集新闻内容,通过HTML5+JS+CSS构建前端界面,并通过emlog的API实现自动发布,所有数据以文件形式存储而不使用数据库。
系统架构
- 采集模块:PHP实现新闻采集
- 存储模块:文件系统存储采集的内容
- 发布模块:通过emlog API发布文章
- 前端界面:HTML5+JS+CSS构建管理界面
1. 采集模块 (news_collector.php)
php
<?php
// 配置文件
define('DATA_DIR', 'data/news/');
define('EMLOG_API_URL', 'http://your-emlog-site/api.php');
define('EMLOG_API_KEY', 'your_api_key_here');
// 自动创建存储目录
if (!file_exists(DATA_DIR)) {
mkdir(DATA_DIR, 0777, true);
}
// 采集新闻函数
function collectNews($sourceUrl) {
$html = file_get_contents($sourceUrl);
// 使用DOM解析新闻内容(这里需要根据实际新闻网站结构调整)
$dom = new DOMDocument();
@$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
// 提取标题 - 根据实际网站调整XPath
$titleNodes = $xpath->query("//h1[@class='article-title']");
$title = $titleNodes->length > 0 ? $titleNodes->item(0)->nodeValue : '无标题';
// 提取内容 - 根据实际网站调整XPath
$contentNodes = $xpath->query("//div[@class='article-content']");
$content = '';
if ($contentNodes->length > 0) {
foreach ($contentNodes->item(0)->childNodes as $node) {
$content .= $dom->saveHTML($node);
}
}
// 提取发布时间
$timeNodes = $xpath->query("//span[@class='publish-time']");
$pubTime = $timeNodes->length > 0 ? strtotime($timeNodes->item(0)->nodeValue) : time();
// 生成唯一ID
$newsId = md5($sourceUrl . time());
// 保存到文件
$newsData = [
'id' => $newsId,
'title' => $title,
'content' => $content,
'source_url' => $sourceUrl,
'pub_time' => $pubTime,
'status' => 'collected' // collected, published
];
file_put_contents(DATA_DIR . $newsId . '.json', json_encode($newsData));
return $newsId;
}
// 发布到emlog
function publishToEmlog($newsId) {
$newsFile = DATA_DIR . $newsId . '.json';
if (!file_exists($newsFile)) {
return false;
}
$newsData = json_decode(file_get_contents($newsFile), true);
$postData = [
'action' => 'addlog',
'token' => EMLOG_API_KEY,
'title' => $newsData['title'],
'content' => $newsData['content'],
'date' => date('Y-m-d H:i:s', $newsData['pub_time']),
'alias' => '',
'excerpt' => mb_substr(strip_tags($newsData['content']), 0, 100),
'allow_remark' => 'y',
'password' => '',
'sortid' => 1, // 分类ID
'tag' => '新闻,采集',
'post' => 'publish'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, EMLOG_API_URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
if (strpos($response, 'success') !== false) {
// 更新状态为已发布
$newsData['status'] = 'published';
file_put_contents($newsFile, json_encode($newsData));
return true;
}
return false;
}
// 示例使用
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action'])) {
switch ($_POST['action']) {
case 'collect':
if (!empty($_POST['url'])) {
$newsId = collectNews($_POST['url']);
echo json_encode(['status' => 'success', 'id' => $newsId]);
}
break;
case 'publish':
if (!empty($_POST['id'])) {
$result = publishToEmlog($_POST['id']);
echo json_encode(['status' => $result ? 'success' : 'error']);
}
break;
}
}
exit;
}
?>
2. 前端管理界面 (index.html)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新闻采集发布系统</title>
<style>
body {
font-family: 'Arial', sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #2c3e50;
}
.section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #eee;
border-radius: 5px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"], textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #2980b9;
}
.news-list {
margin-top: 20px;
}
.news-item {
padding: 15px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.news-item:last-child {
border-bottom: none;
}
.news-title {
font-weight: bold;
flex: 1;
}
.news-status {
padding: 5px 10px;
border-radius: 3px;
font-size: 12px;
}
.status-collected {
background-color: #f39c12;
color: white;
}
.status-published {
background-color: #2ecc71;
color: white;
}
.news-actions {
margin-left: 15px;
}
</style>
</head>
<body>
<div class="container">
<h1>新闻采集发布系统</h1>
<div class="section">
<h2>采集新文章</h2>
<div class="form-group">
<label for="news-url">新闻URL:</label>
<input type="text" id="news-url" placeholder="输入新闻网址">
</div>
<button id="collect-btn">开始采集</button>
</div>
<div class="section">
<h2>已采集文章</h2>
<div class="news-list" id="news-list">
<!-- 新闻列表将通过JS动态加载 -->
</div>
</div>
</div>
<script>
// 加载新闻列表
function loadNewsList() {
fetch('news_collector.php?action=list')
.then(response => response.json())
.then(data => {
const newsList = document.getElementById('news-list');
newsList.innerHTML = '';
if (data.length === 0) {
newsList.innerHTML = '<p>暂无采集的新闻</p>';
return;
}
data.forEach(news => {
const newsItem = document.createElement('div');
newsItem.className = 'news-item';
const statusClass = news.status === 'published' ? 'status-published' : 'status-collected';
newsItem.innerHTML = `
<div class="news-title">${news.title}</div>
<div class="news-status ${statusClass}">${news.status === 'published' ? '已发布' : '已采集'}</div>
<div class="news-actions">
${news.status === 'collected' ? `<button onclick="publishNews('${news.id}')">发布</button>` : ''}
<button onclick="deleteNews('${news.id}')">删除</button>
</div>
`;
newsList.appendChild(newsItem);
});
})
.catch(error => {
console.error('Error:', error);
});
}
// 采集新闻
document.getElementById('collect-btn').addEventListener('click', () => {
const url = document.getElementById('news-url').value.trim();
if (!url) {
alert('请输入新闻URL');
return;
}
const formData = new FormData();
formData.append('action', 'collect');
formData.append('url', url);
fetch('news_collector.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
alert('采集成功!');
document.getElementById('news-url').value = '';
loadNewsList();
} else {
alert('采集失败');
}
})
.catch(error => {
console.error('Error:', error);
alert('采集过程中发生错误');
});
});
// 发布新闻
function publishNews(newsId) {
if (!confirm('确定要发布这篇文章吗?')) return;
const formData = new FormData();
formData.append('action', 'publish');
formData.append('id', newsId);
fetch('news_collector.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
alert('发布成功!');
loadNewsList();
} else {
alert('发布失败');
}
})
.catch(error => {
console.error('Error:', error);
alert('发布过程中发生错误');
});
}
// 删除新闻
function deleteNews(newsId) {
if (!confirm('确定要删除这篇文章吗?')) return;
fetch(`news_collector.php?action=delete&id=${newsId}`)
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
alert('删除成功!');
loadNewsList();
} else {
alert('删除失败');
}
})
.catch(error => {
console.error('Error:', error);
alert('删除过程中发生错误');
});
}
// 页面加载时获取新闻列表
document.addEventListener('DOMContentLoaded', loadNewsList);
</script>
</body>
</html>
3. 完善采集模块 (添加列表和删除功能)
在news_collector.php中添加以下代码:
php
// 获取新闻列表
function getNewsList() {
$newsList = [];
$files = glob(DATA_DIR . '*.json');
foreach ($files as $file) {
$content = file_get_contents($file);
$newsData = json_decode($content, true);
$newsList[] = [
'id' => $newsData['id'],
'title' => $newsData['title'],
'status' => $newsData['status'],
'pub_time' => $newsData['pub_time']
];
}
// 按发布时间排序
usort($newsList, function($a, $b) {
return $b['pub_time'] - $a['pub_time'];
});
return $newsList;
}
// 删除新闻
function deleteNews($newsId) {
$newsFile = DATA_DIR . $newsId . '.json';
if (file_exists($newsFile)) {
unlink($newsFile);
return true;
}
return false;
}
// 处理GET请求
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action'])) {
switch ($_GET['action']) {
case 'list':
echo json_encode(getNewsList());
break;
case 'delete':
if (!empty($_GET['id'])) {
$result = deleteNews($_GET['id']);
echo json_encode(['status' => $result ? 'success' : 'error']);
}
break;
}
exit;
}
系统部署说明
-
将上述代码保存为三个文件:
news_collector.php
(采集和发布逻辑)index.html
(前端管理界面)data/
目录 (用于存储采集的新闻数据)
-
配置emlog API:
- 确保你的emlog博客已安装API插件
- 在代码中设置正确的
EMLOG_API_URL
和EMLOG_API_KEY
-
系统功能:
- 输入新闻URL采集文章
- 查看已采集文章列表
- 将文章发布到emlog
- 删除不需要的文章
-
安全建议:
- 为管理界面添加密码保护
- 限制可采集的域名白名单
- 定期清理旧数据
扩展建议
- 可以添加定时任务自动采集指定网站的新闻
- 增加多站点采集支持
- 添加内容过滤和格式化功能
- 实现分类和标签的自动识别
- 添加图片本地化功能
这个系统完全基于文件存储,不使用数据库,适合小型新闻采集发布需求。