本文目录导读:

我来为你提供一份关于PHP项目中用户行为追踪与漏斗分析的完整解决方案。
数据采集方案
数据库表结构设计
-- 用户行为日志表
CREATE TABLE `user_behavior_logs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户ID',
`session_id` varchar(64) NOT NULL COMMENT '会话ID',
`event_type` varchar(50) NOT NULL COMMENT '事件类型(visit/click/purchase等)',
`event_name` varchar(100) NOT NULL COMMENT '事件名称',
`event_value` text COMMENT '事件参数(JSON格式)',
`page_url` varchar(500) NOT NULL COMMENT '页面URL',
`referrer_url` varchar(500) DEFAULT NULL COMMENT '来源URL',
`ip` varchar(45) DEFAULT NULL COMMENT 'IP地址',
`user_agent` text COMMENT '浏览器UA',
`device_type` varchar(20) DEFAULT NULL COMMENT '设备类型',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_event_type` (`event_type`),
KEY `idx_created_at` (`created_at`),
KEY `idx_session_id` (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户会话表(用于追踪完整流程)
CREATE TABLE `user_sessions` (
`id` varchar(64) NOT NULL,
`user_id` int(11) NOT NULL,
`start_time` timestamp NOT NULL,
`end_time` timestamp NULL,
`first_page` varchar(500) DEFAULT NULL,
`last_page` varchar(500) DEFAULT NULL,
`page_views` int(11) DEFAULT 1,
`device_info` text,
`ip` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_start_time` (`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
PHP数据采集实现
<?php
class UserBehaviorTracker {
private $db;
private $userId;
private $sessionId;
public function __construct($db) {
$this->db = $db;
$this->userId = $this->getCurrentUserId();
$this->sessionId = $this->getOrCreateSessionId();
}
/**
* 记录用户行为事件
*/
public function track($eventType, $eventName, $eventValue = []) {
$data = [
'user_id' => $this->userId,
'session_id' => $this->sessionId,
'event_type' => $eventType,
'event_name' => $eventName,
'event_value' => json_encode($eventValue, JSON_UNESCAPED_UNICODE),
'page_url' => $_SERVER['REQUEST_URI'] ?? '',
'referrer_url' => $_SERVER['HTTP_REFERER'] ?? '',
'ip' => $this->getClientIp(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'device_type' => $this->detectDeviceType($_SERVER['HTTP_USER_AGENT'] ?? ''),
'created_at' => date('Y-m-d H:i:s')
];
$this->saveToDatabase($data);
$this->updateSession();
}
/**
* 记录页面访问
*/
public function trackPageView($pageName = '') {
$this->track('visit', $pageName ?: 'page_view', ['page_name' => $pageName]);
}
/**
* 记录按钮点击
*/
public function trackClick($buttonName, $extraData = []) {
$this->track('click', $buttonName, $extraData);
}
/**
* 记录用户转化
*/
public function trackConversion($conversionType, $value = null) {
$this->track('conversion', $conversionType, ['value' => $value]);
}
private function getCurrentUserId() {
return $_SESSION['user_id'] ?? 0;
}
private function getOrCreateSessionId() {
if (!isset($_SESSION['tracking_session_id'])) {
$_SESSION['tracking_session_id'] = uniqid('sess_', true);
}
return $_SESSION['tracking_session_id'];
}
private function saveToDatabase($data) {
$sql = "INSERT INTO user_behavior_logs
(user_id, session_id, event_type, event_name, event_value,
page_url, referrer_url, ip, user_agent, device_type, created_at)
VALUES
(:user_id, :session_id, :event_type, :event_name, :event_value,
:page_url, :referrer_url, :ip, :user_agent, :device_type, :created_at)";
$stmt = $this->db->prepare($sql);
$stmt->execute($data);
}
private function updateSession() {
// 更新会话信息
$sql = "INSERT INTO user_sessions (id, user_id, start_time, first_page, ip)
VALUES (:id, :user_id, NOW(), :page_url, :ip)
ON DUPLICATE KEY UPDATE
end_time = NOW(),
page_views = page_views + 1,
last_page = :page_url";
$stmt = $this->db->prepare($sql);
$stmt->execute([
'id' => $this->sessionId,
'user_id' => $this->userId,
'page_url' => $_SERVER['REQUEST_URI'] ?? '',
'ip' => $this->getClientIp()
]);
}
private function getClientIp() {
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
return trim($ips[0]);
}
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
private function detectDeviceType($userAgent) {
if (preg_match('/Mobile|Android|iPhone|iPad/i', $userAgent)) {
return 'mobile';
} elseif (preg_match('/Tablet|iPad/i', $userAgent)) {
return 'tablet';
}
return 'desktop';
}
}
漏斗分析实现
漏斗模型类
<?php
class FunnelAnalyzer {
private $db;
public function __construct($db) {
$this->db = $db;
}
/**
* 创建漏斗分析
* @param array $steps 步骤定义 [['event_type'=>'visit','event_name'=>'homepage'], ...]
* @param string $startDate 开始日期
* @param string $endDate 结束日期
* @param array $filters 过滤条件
*/
public function analyzeFunnel($steps, $startDate, $endDate, $filters = []) {
$results = [];
$totalUsers = 0;
foreach ($steps as $index => $step) {
$stepData = $this->getStepData($step, $startDate, $endDate, $filters, $index);
$results[] = $stepData;
if ($index == 0) {
$totalUsers = $stepData['unique_users'];
}
}
// 计算漏斗转化率
return $this->calculateConversionRates($results, $totalUsers);
}
private function getStepData($step, $startDate, $endDate, $filters, $stepIndex) {
$sql = "SELECT COUNT(DISTINCT user_id) as unique_users,
COUNT(*) as total_events
FROM user_behavior_logs
WHERE event_type = :event_type
AND event_name = :event_name
AND created_at BETWEEN :start_date AND :end_date";
// 如果是后续步骤,需要限定用户之前已完成前面步骤
if ($stepIndex > 0) {
$sql .= " AND user_id IN (
SELECT DISTINCT user_id FROM user_behavior_logs
WHERE event_type = :prev_event_type
AND event_name = :prev_event_name
AND created_at BETWEEN :start_date AND :end_date
)";
}
// 添加额外过滤条件
$params = [
'event_type' => $step['event_type'],
'event_name' => $step['event_name'],
'start_date' => $startDate,
'end_date' => $endDate
];
if (!empty($filters)) {
$sql .= $this->buildFilterConditions($filters, $params);
}
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return [
'step_name' => $step['name'] ?? $step['event_name'],
'event_type' => $step['event_type'],
'event_name' => $step['event_name'],
'unique_users' => (int)$result['unique_users'],
'total_events' => (int)$result['total_events']
];
}
private function calculateConversionRates($steps, $totalUsers) {
$funnelData = [];
foreach ($steps as $index => $step) {
$currentUsers = $step['unique_users'];
// 计算转化率
$overallRate = $totalUsers > 0 ? round(($currentUsers / $totalUsers) * 100, 2) : 0;
$stepRate = $index > 0 ?
($steps[$index - 1]['unique_users'] > 0 ?
round(($currentUsers / $steps[$index - 1]['unique_users']) * 100, 2) : 0) : 100;
$funnelData[] = [
'step' => $step['step_name'],
'users' => $currentUsers,
'events' => $step['total_events'],
'step_conversion_rate' => $stepRate,
'overall_conversion_rate' => $overallRate,
'drop_off' => $index > 0 ? $steps[$index - 1]['unique_users'] - $currentUsers : 0
];
}
return $funnelData;
}
private function buildFilterConditions($filters, &$params) {
$conditions = '';
foreach ($filters as $field => $value) {
if (is_array($value)) {
$placeholders = [];
foreach ($value as $i => $v) {
$key = "filter_{$field}_{$i}";
$placeholders[] = ":$key";
$params[$key] = $v;
}
$conditions .= " AND $field IN (" . implode(',', $placeholders) . ")";
} else {
$key = "filter_{$field}";
$conditions .= " AND $field = :$key";
$params[$key] = $value;
}
}
return $conditions;
}
}
时间序列分析
<?php
class TimeSeriesFunnelAnalyzer extends FunnelAnalyzer {
/**
* 按天分析漏斗趋势
*/
public function analyzeDailyFunnel($steps, $startDate, $endDate, $filters = []) {
$dailyData = [];
$current = strtotime($startDate);
$end = strtotime($endDate);
while ($current <= $end) {
$date = date('Y-m-d', $current);
$dayStart = $date . ' 00:00:00';
$dayEnd = $date . ' 23:59:59';
$funnel = $this->analyzeFunnel($steps, $dayStart, $dayEnd, $filters);
$dailyData[$date] = $funnel;
$current = strtotime('+1 day', $current);
}
return $dailyData;
}
/**
* 获取趋势数据用于图表
*/
public function getTrendData($steps, $startDate, $endDate, $filters = []) {
$dailyFunnel = $this->analyzeDailyFunnel($steps, $startDate, $endDate, $filters);
$trendData = [
'dates' => [],
'steps' => []
];
foreach ($steps as $step) {
$trendData['steps'][$step['name'] ?? $step['event_name']] = [];
}
foreach ($dailyFunnel as $date => $funnel) {
$trendData['dates'][] = $date;
foreach ($funnel as $stepData) {
$stepName = $stepData['step'];
$trendData['steps'][$stepName][] = $stepData['users'];
}
}
return $trendData;
}
}
高级漏斗分析功能
<?php
class AdvancedFunnelAnalyzer extends FunnelAnalyzer {
/**
* 分段分析(按设备、渠道等)
*/
public function segmentFunnel($steps, $startDate, $endDate, $segmentBy = 'device_type') {
$segments = $this->getDistinctValues($segmentBy, $startDate, $endDate);
$segmentedResults = [];
foreach ($segments as $segment) {
$filters = [$segmentBy => $segment];
$funnel = $this->analyzeFunnel($steps, $startDate, $endDate, $filters);
$segmentedResults[$segment] = $funnel;
}
return $segmentedResults;
}
/**
* 用户路径分析
*/
public function getUserPathAnalysis($userId, $limit = 20) {
$sql = "SELECT event_type, event_name, page_url, created_at
FROM user_behavior_logs
WHERE user_id = :user_id
ORDER BY created_at
LIMIT :limit";
$stmt = $this->db->prepare($sql);
$stmt->execute(['user_id' => $userId, 'limit' => $limit]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* 流失用户分析
*/
public function analyzeDropOffUsers($steps, $startDate, $endDate) {
$droppedAtStep = [];
foreach ($steps as $index => $step) {
if ($index > 0) {
$sql = "SELECT DISTINCT l1.user_id
FROM user_behavior_logs l1
WHERE l1.event_type = :prev_type
AND l1.event_name = :prev_name
AND l1.created_at BETWEEN :start AND :end
AND NOT EXISTS (
SELECT 1 FROM user_behavior_logs l2
WHERE l2.user_id = l1.user_id
AND l2.event_type = :curr_type
AND l2.event_name = :curr_name
AND l2.created_at BETWEEN :start AND :end
)";
$stmt = $this->db->prepare($sql);
$stmt->execute([
'prev_type' => $steps[$index - 1]['event_type'],
'prev_name' => $steps[$index - 1]['event_name'],
'curr_type' => $step['event_type'],
'curr_name' => $step['event_name'],
'start' => $startDate,
'end' => $endDate
]);
$droppedAtStep[$step['name'] ?? $step['event_name']] = [
'count' => $stmt->rowCount(),
'user_ids' => $stmt->fetchAll(PDO::FETCH_COLUMN)
];
}
}
return $droppedAtStep;
}
private function getDistinctValues($field, $startDate, $endDate) {
$sql = "SELECT DISTINCT $field FROM user_behavior_logs
WHERE $field IS NOT NULL
AND created_at BETWEEN :start AND :end";
$stmt = $this->db->prepare($sql);
$stmt->execute(['start' => $startDate, 'end' => $endDate]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
}
前端集成与展示
JavaScript跟踪代码
// tracking.js
class UserBehaviorTracker {
constructor(config) {
this.config = {
trackPageViews: true,
trackClicks: true,
trackFormSubmissions: true,
scrollTracking: false,
serverUrl: '/api/track',
...config
};
this.init();
}
init() {
if (this.config.trackPageViews) {
this.trackPageView();
}
if (this.config.trackClicks) {
this.bindClickTracking();
}
if (this.config.trackFormSubmissions) {
this.bindFormTracking();
}
if (this.config.scrollTracking) {
this.initScrollTracking();
}
}
trackPageView() {
this.sendEvent('visit', 'page_view', {
page: window.location.pathname,
title: document.title,
referrer: document.referrer
});
}
trackEvent(eventType, eventName, data = {}) {
this.sendEvent(eventType, eventName, data);
}
bindClickTracking() {
document.addEventListener('click', (e) => {
const target = e.target;
const dataTrack = target.getAttribute('data-track');
const dataTrackValue = target.getAttribute('data-track-value');
if (dataTrack) {
this.sendEvent('click', dataTrack, {
value: dataTrackValue || target.innerText || target.href,
element: target.tagName,
id: target.id,
className: target.className
});
}
}, true);
}
bindFormTracking() {
document.addEventListener('submit', (e) => {
const form = e.target;
const formName = form.getAttribute('name') || form.id || 'unknown_form';
this.sendEvent('form_submit', formName, {
fields: this.getFormFields(form)
});
});
}
initScrollTracking() {
let scrollTimeout;
window.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
const scrollPercent = Math.round(
(window.scrollY + window.innerHeight) / document.documentElement.scrollHeight * 100
);
if (scrollPercent >= 25 && scrollPercent < 50) {
this.sendEvent('scroll', '25_percent');
} else if (scrollPercent >= 50 && scrollPercent < 75) {
this.sendEvent('scroll', '50_percent');
} else if (scrollPercent >= 75 && scrollPercent < 100) {
this.sendEvent('scroll', '75_percent');
} else if (scrollPercent >= 100) {
this.sendEvent('scroll', '100_percent');
}
}, 500);
});
}
sendEvent(eventType, eventName, data = {}) {
const payload = {
event_type: eventType,
event_name: eventName,
event_value: data,
timestamp: new Date().toISOString(),
page_url: window.location.href,
user_agent: navigator.userAgent
};
// 使用Beacon API或fetch发送数据
if (navigator.sendBeacon) {
navigator.sendBeacon(this.config.serverUrl, JSON.stringify(payload));
} else {
fetch(this.config.serverUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
}
}
getFormFields(form) {
const fields = {};
const formData = new FormData(form);
for (let [key, value] of formData.entries()) {
fields[key] = value;
}
return fields;
}
}
// 使用示例
const tracker = new UserBehaviorTracker({
trackPageViews: true,
trackClicks: true,
trackFormSubmissions: true,
scrollTracking: true,
serverUrl: '/api/track-event'
});
PHP后端接收接口
<?php
// api/track-event.php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/UserBehaviorTracker.php';
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['event_type']) || !isset($input['event_name'])) {
http_response_code(400);
echo json_encode(['error' => 'Invalid input']);
exit;
}
$db = Database::getConnection();
$tracker = new UserBehaviorTracker($db);
$tracker->track(
$input['event_type'],
$input['event_name'],
$input['event_value'] ?? []
);
http_response_code(200);
echo json_encode(['success' => true]);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
数据报表与API
漏斗分析API
<?php
// api/funnel-analysis.php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../analytics/FunnelAnalyzer.php';
require_once __DIR__ . '/../analytics/AdvancedFunnelAnalyzer.php';
class FunnelAPI {
private $db;
private $analyzer;
public function __construct() {
$this->db = Database::getConnection();
}
public function handleRequest() {
$action = $_GET['action'] ?? 'funnel';
switch ($action) {
case 'funnel':
$this->getFunnelData();
break;
case 'trend':
$this->getTrendData();
break;
case 'segment':
$this->getSegmentedData();
break;
case 'dropoff':
$this->getDropOffUsers();
break;
default:
$this->response(['error' => 'Invalid action'], 400);
}
}
private function getFunnelData() {
$steps = $this->getRequestSteps();
$startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
$endDate = $_GET['end_date'] ?? date('Y-m-d');
$analyzer = new FunnelAnalyzer($this->db);
$data = $analyzer->analyzeFunnel($steps, $startDate, $endDate);
$this->response([
'success' => true,
'data' => $data,
'metadata' => [
'start_date' => $startDate,
'end_date' => $endDate,
'total_steps' => count($steps)
]
]);
}
private function getTrendData() {
$steps = $this->getRequestSteps();
$startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-7 days'));
$endDate = $_GET['end_date'] ?? date('Y-m-d');
$analyzer = new TimeSeriesFunnelAnalyzer($this->db);
$data = $analyzer->getTrendData($steps, $startDate, $endDate);
$this->response([
'success' => true,
'data' => $data
]);
}
private function getSegmentedData() {
$steps = $this->getRequestSteps();
$startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
$endDate = $_GET['end_date'] ?? date('Y-m-d');
$segmentBy = $_GET['segment_by'] ?? 'device_type';
$analyzer = new AdvancedFunnelAnalyzer($this->db);
$data = $analyzer->segmentFunnel($steps, $startDate, $endDate, $segmentBy);
$this->response([
'success' => true,
'data' => $data,
'segment_by' => $segmentBy
]);
}
private function getDropOffUsers() {
$steps = $this->getRequestSteps();
$startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
$endDate = $_GET['end_date'] ?? date('Y-m-d');
$analyzer = new AdvancedFunnelAnalyzer($this->db);
$data = $analyzer->analyzeDropOffUsers($steps, $startDate, $endDate);
$this->response([
'success' => true,
'data' => $data
]);
}
private function getRequestSteps() {
$stepsJson = $_GET['steps'] ?? '[]';
$steps = json_decode($stepsJson, true);
if (empty($steps)) {
// 默认漏斗步骤
$steps = [
['event_type' => 'visit', 'event_name' => 'page_view', 'name' => '访问首页'],
['event_type' => 'visit', 'event_name' => 'product_page', 'name' => '浏览商品'],
['event_type' => 'click', 'event_name' => 'add_to_cart', 'name' => '加入购物车'],
['event_type' => 'click', 'event_name' => 'checkout', 'name' => '开始结算'],
['event_type' => 'conversion', 'event_name' => 'purchase', 'name' => '完成购买']
];
}
return $steps;
}
private function response($data, $statusCode = 200) {
http_response_code($statusCode);
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
}
// 处理请求
$api = new FunnelAPI();
$api->handleRequest();
使用示例
在前端页面中使用
<!-- 在页面中添加跟踪代码 -->
<script src="/js/tracking.js"></script>
<script>
// 初始化跟踪器
const tracker = new UserBehaviorTracker({
trackPageViews: true,
trackClicks: true,
trackFormSubmissions: true,
serverUrl: '/api/track-event'
});
// 手动跟踪特定事件
function trackAddToCart(productId, productName) {
tracker.trackEvent('click', 'add_to_cart', {
product_id: productId,
product_name: productName
});
}
function trackPurchase(orderId, total) {
tracker.trackEvent('conversion', 'purchase', {
order_id: orderId,
total: total
});
}
</script>
<!-- 使用data-track属性自动跟踪点击 -->
<button data-track="cta_button" data-track-value="立即购买">
立即购买
</button>
<a href="/product/123" data-track="product_click" data-track-value="商品123">
查看商品
</a>
PHP后端调用
<?php
// 在控制器中使用
class OrderController {
public function placeOrder() {
// 处理订单逻辑
// 跟踪购买事件
$tracker = new UserBehaviorTracker($db);
$tracker->trackConversion('purchase', [
'order_id' => $orderId,
'total' => $totalAmount,
'product_count' => $productCount
]);
// 重定向到成功页面
header('Location: /order/success/' . $orderId);
}
}
前端调用API获取漏斗数据
// 获取漏斗数据并渲染图表
async function renderFunnelChart() {
const steps = [
{ event_type: 'visit', event_name: 'page_view', name: '访问首页' },
{ event_type: 'visit', event_name: 'product_page', name: '浏览商品' },
{ event_type: 'click', event_name: 'add_to_cart', name: '加入购物车' },
{ event_type: 'click', event_name: 'checkout', name: '开始结算' },
{ event_type: 'conversion', event_name: 'purchase', name: '完成购买' }
];
const response = await fetch(`/api/funnel-analysis.php?action=funnel&steps=${JSON.stringify(steps)}&start_date=2024-01-01&end_date=2024-01-31`);
const result = await response.json();
if (result.success) {
createFunnelChart(result.data);
}
}
function createFunnelChart(funnelData) {
// 使用Chart.js或其他图表库渲染漏斗图
const ctx = document.getElementById('funnelChart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: funnelData.map(d => d.step),
datasets: [{
label: '用户数',
data: funnelData.map(d => d.users),
backgroundColor: [
'rgba(54, 162, 235, 0.8)',
'rgba(75, 192, 192, 0.8)',
'rgba(255, 206, 86, 0.8)',
'rgba(255, 159, 64, 0.8)',
'rgba(255, 99, 132, 0.8)'
],
borderWidth: 1
}]
},
options: {
indexAxis: 'y',
plugins: {
tooltip: {
callbacks: {
afterLabel: function(context) {
const data = funnelData[context.dataIndex];
return [
`转化率: ${data.step_conversion_rate}%`,
`整体转化率: ${data.overall_conversion_rate}%`,
`流失用户: ${data.drop_off}`
];
}
}
}
},
scales: {
x: {
beginAtZero: true
}
}
}
});
}
这个完整的PHP用户行为与漏斗分析系统包含了数据采集、存储、分析、API和前端展示的完整解决方案,你可以根据实际需求进行调整和扩展。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播