本文目录导读:

我来为您提供一个完整的PHP抓取网页内容并存入数据库的解决方案:
数据库准备
CREATE TABLE IF NOT EXISTS `scraped_data` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `url` VARCHAR(500) NOT NULL, VARCHAR(500), `content` TEXT, `images` TEXT, `links` TEXT, `scraped_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX `idx_url` (`url`(191)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
基础抓取类
<?php
class WebScraper {
private $pdo;
private $timeout = 30;
private $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
public function __construct($pdo) {
$this->pdo = $pdo;
}
/**
* 抓取网页内容
* @param string $url 目标URL
* @return array 抓取的数据
*/
public function scrape($url) {
try {
// 获取网页内容
$html = $this->fetchContent($url);
if (!$html) {
throw new Exception('无法获取网页内容');
}
// 解析网页内容
$data = $this->parseContent($html, $url);
// 保存到数据库
$this->saveToDatabase($data);
return $data;
} catch (Exception $e) {
error_log('抓取失败: ' . $e->getMessage());
return false;
}
}
/**
* 获取网页内容
*/
private function fetchContent($url) {
$ch = curl_init();
$options = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_ENCODING => '', // 支持压缩
CURLOPT_HTTPHEADER => [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
],
];
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
error_log('CURL错误: ' . curl_error($ch));
return false;
}
curl_close($ch);
if ($httpCode !== 200) {
error_log("HTTP状态码: $httpCode");
return false;
}
return $content;
}
/**
* 解析网页内容
*/
private function parseContent($html, $url) {
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML('<?xml encoding="UTF-8">' . $html);
libxml_clear_errors();
$xpath = new DOMXPath($dom);
// 提取标题
$titleNode = $xpath->query('//title');
$title = $titleNode->length > 0 ? trim($titleNode->item(0)->textContent) : '';
// 提取主体内容(可根据需要调整选择器)
$contentNode = $xpath->query('//article | //main | //div[@class="content"] | //div[@id="content"]');
$content = '';
if ($contentNode->length > 0) {
$content = $this->cleanContent($contentNode->item(0)->textContent);
} else {
// 回退到body内容
$bodyNode = $dom->getElementsByTagName('body');
if ($bodyNode->length > 0) {
$content = $this->cleanContent($bodyNode->item(0)->textContent);
}
}
// 提取图片
$images = [];
$imgNodes = $dom->getElementsByTagName('img');
foreach ($imgNodes as $img) {
$src = $img->getAttribute('src');
if ($src && filter_var($src, FILTER_VALIDATE_URL) === false) {
$src = $this->resolveUrl($url, $src);
}
if ($src) {
$images[] = $src;
}
}
// 提取链接
$links = [];
$linkNodes = $dom->getElementsByTagName('a');
foreach ($linkNodes as $link) {
$href = $link->getAttribute('href');
if ($href && !preg_match('/^(javascript|mailto|tel):/i', $href)) {
if (filter_var($href, FILTER_VALIDATE_URL) === false) {
$href = $this->resolveUrl($url, $href);
}
$links[] = [
'text' => trim($link->textContent),
'href' => $href
];
}
}
return [
'url' => $url,
'title' => $title,
'content' => $content,
'images' => json_encode($images),
'links' => json_encode($links),
'scraped_at' => date('Y-m-d H:i:s')
];
}
/**
* 清理内容
*/
private function cleanContent($content) {
// 去除多余空白
$content = preg_replace('/\s+/', ' ', $content);
// 去除特殊字符
$content = trim($content);
return $content;
}
/**
* 解析相对URL为绝对URL
*/
private function resolveUrl($baseUrl, $relativeUrl) {
// 解析基础URL
$parsedBase = parse_url($baseUrl);
// 如果是完整的URL则直接返回
if (filter_var($relativeUrl, FILTER_VALIDATE_URL)) {
return $relativeUrl;
}
// 处理相对URL
if (strpos($relativeUrl, '//') === 0) {
return $parsedBase['scheme'] . ':' . $relativeUrl;
}
if (strpos($relativeUrl, '/') === 0) {
return $parsedBase['scheme'] . '://' . $parsedBase['host'] . $relativeUrl;
}
$path = isset($parsedBase['path']) ? $parsedBase['path'] : '/';
$path = preg_replace('/[^\/]*$/', '', $path);
return $parsedBase['scheme'] . '://' . $parsedBase['host'] . $path . $relativeUrl;
}
/**
* 保存到数据库
*/
private function saveToDatabase($data) {
try {
$stmt = $this->pdo->prepare(
"INSERT INTO scraped_data (url, title, content, images, links, scraped_at)
VALUES (:url, :title, :content, :images, :links, :scraped_at)"
);
return $stmt->execute($data);
} catch (PDOException $e) {
error_log('数据库保存失败: ' . $e->getMessage());
return false;
}
}
/**
* 检查URL是否已存在
*/
public function isUrlExists($url) {
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM scraped_data WHERE url = :url");
$stmt->execute([':url' => $url]);
return $stmt->fetchColumn() > 0;
}
}
?>
使用示例
<?php
// 加载数据库配置
require_once 'config.php';
// 创建PDO连接
try {
$pdo = new PDO(
"mysql:host=$db_host;dbname=$db_name;charset=utf8mb4",
$db_user,
$db_pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
$scraper = new WebScraper($pdo);
// 要抓取的URL列表
$urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
];
foreach ($urls as $url) {
// 检查是否已存在
if ($scraper->isUrlExists($url)) {
echo "URL已存在,跳过: $url\n";
continue;
}
echo "开始抓取: $url\n";
$result = $scraper->scrape($url);
if ($result) {
echo "成功抓取并保存: {$result['title']}\n";
} else {
echo "抓取失败: $url\n";
}
// 避免请求过快
usleep(rand(500000, 1000000)); // 0.5-1秒延迟
}
?>
配置文件示例 (config.php)
<?php
$db_host = 'localhost';
$db_name = 'web_scraper';
$db_user = 'root';
$db_pass = 'your_password';
// 可选:代理配置
$proxy_config = [
'proxy_type' => CURLPROXY_HTTP,
'proxy_host' => '127.0.0.1',
'proxy_port' => 8080,
'proxy_user' => '',
'proxy_pass' => '',
];
// 可选:多线程配置(需要pcntl扩展)
$threads = 5;
?>
增强功能(可选)
支持Cookie和会话
private function fetchContentWithCookies($url, $cookies) {
$cookieFile = tempnam('/tmp', 'cookie_');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
// ... 其他设置
}
支持JavaScript渲染
// 使用无头浏览器(需要安装Puppeteer)
public function scrapeWithHeadlessBrowser($url) {
$html = shell_exec("node render.js \"$url\"");
// 然后解析HTML
}
注意事项
- 遵守robots.txt和网站服务条款
- 设置适当的请求延迟,避免给目标网站造成压力
- 处理编码问题,确保正确解析UTF-8、GBK等编码
- 错误处理和日志记录很重要
- 数据库连接使用PDO以增强安全性
- 定期清理不需要的数据
这个解决方案已经包含常用的网页抓取功能,您可以根据具体需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播