Python中如何实现电影爬虫并用Django展示结果并支持在线播放

最近学 Django,写了个小工具,从「东北大学 IPv6 视频直播测试站」爬取电影名称和播放地址,然后用电影名从豆瓣获取海报、简介以及评分,并过滤掉评分低的电影。 其实就是个自带展示界面的小爬虫 :)

我这里无法访问 IPv6 网站,所以最初的目的是用 nginx 在服务器上反代一下那个网站;后来发现电影质量参差不齐,而且没有电影分类(科幻 /喜剧)和简介,每次都要去豆瓣看看太麻烦,就有了这个小工具。

展示地址:https://tv.tulip.ink/,repo:https://github.com/cshuaimin/tv

当然这一切都还很简陋,但随着项目学习起来会轻松一点,一起加油吧~


Python中如何实现电影爬虫并用Django展示结果并支持在线播放

15 回复

Chrome 无法加载 flash


我来帮你实现一个电影爬虫并用Django展示和在线播放的完整方案。

核心架构:

  1. 爬虫模块 - 使用requests和BeautifulSoup抓取电影数据
  2. Django模型 - 存储电影信息
  3. 视图和模板 - 展示电影列表和播放页面
  4. 播放器 - 使用HTML5 video标签或第三方播放器

完整代码实现:

1. 首先创建Django项目结构:

django-admin startproject movie_project
cd movie_project
python manage.py startapp movies

2. 修改movies/models.py:

from django.db import models

class Movie(models.Model):
    title = models.CharField(max_length=200, verbose_name='电影标题')
    cover_url = models.URLField(verbose_name='封面URL')
    play_url = models.URLField(verbose_name='播放地址')
    description = models.TextField(blank=True, verbose_name='描述')
    category = models.CharField(max_length=50, blank=True, verbose_name='分类')
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

3. 创建爬虫脚本spider.py

import requests
from bs4 import BeautifulSoup
import json
from movies.models import Movie
import time

class MovieSpider:
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
    
    def crawl_example_site(self):
        """示例爬虫 - 实际使用时替换为目标网站"""
        try:
            # 这里以示例网站为例,实际需要替换为目标电影网站
            url = "https://example-movies.com/list"
            response = requests.get(url, headers=self.headers, timeout=10)
            response.encoding = 'utf-8'
            
            soup = BeautifulSoup(response.text, 'html.parser')
            movies = []
            
            # 假设电影信息在特定的div中,根据实际网站结构调整
            movie_items = soup.find_all('div', class_='movie-item')
            
            for item in movie_items[:10]:  # 限制爬取数量
                title = item.find('h3').text.strip()
                cover = item.find('img')['src']
                play_link = item.find('a', class_='play-link')['href']
                
                # 保存到数据库
                movie, created = Movie.objects.get_or_create(
                    title=title,
                    defaults={
                        'cover_url': cover,
                        'play_url': play_link,
                        'description': f'爬取的电影:{title}'
                    }
                )
                
                if created:
                    print(f'新增电影:{title}')
                else:
                    print(f'电影已存在:{title}')
                
                time.sleep(1)  # 礼貌爬取
            
            return len(movies)
            
        except Exception as e:
            print(f'爬取失败:{e}')
            return 0

# 运行爬虫
if __name__ == '__main__':
    spider = MovieSpider()
    count = spider.crawl_example_site()
    print(f'爬取完成,共处理{count}部电影')

4. 创建movies/views.py:

from django.shortcuts import render
from .models import Movie
from django.views.generic import ListView, DetailView
from django.http import JsonResponse
import subprocess

class MovieListView(ListView):
    model = Movie
    template_name = 'movies/movie_list.html'
    context_object_name = 'movies'
    paginate_by = 12

class MovieDetailView(DetailView):
    model = Movie
    template_name = 'movies/movie_detail.html'
    context_object_name = 'movie'

def start_crawl(request):
    """启动爬虫的视图"""
    if request.method == 'POST':
        try:
            # 异步执行爬虫
            subprocess.Popen(['python', 'spider.py'])
            return JsonResponse({'status': 'success', 'message': '爬虫已启动'})
        except Exception as e:
            return JsonResponse({'status': 'error', 'message': str(e)})
    return JsonResponse({'status': 'error', 'message': '无效请求'})

5. 创建movies/templates/movies/movie_list.html:

<!DOCTYPE html>
<html>
<head>
    <title>电影列表</title>
    <style>
        .movie-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        .movie-card {
            border: 1px solid #ddd;
            border-radius: 8px;
            overflow: hidden;
            transition: transform 0.3s;
        }
        .movie-card:hover {
            transform: translateY(-5px);
        }
        .movie-cover {
            width: 100%;
            height: 300px;
            object-fit: cover;
        }
        .movie-info {
            padding: 15px;
        }
        .play-btn {
            display: block;
            width: 100%;
            padding: 10px;
            background: #007bff;
            color: white;
            text-align: center;
            text-decoration: none;
            border: none;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>电影列表</h1>
    
    <button onclick="startCrawl()">启动爬虫</button>
    
    <div class="movie-grid">
        {% for movie in movies %}
        <div class="movie-card">
            <img src="{{ movie.cover_url }}" alt="{{ movie.title }}" class="movie-cover">
            <div class="movie-info">
                <h3>{{ movie.title }}</h3>
                <a href="{% url 'movie_detail' movie.id %}" class="play-btn">播放</a>
            </div>
        </div>
        {% endfor %}
    </div>
    
    <script>
    function startCrawl() {
        fetch('/start-crawl/', {
            method: 'POST',
            headers: {'X-CSRFToken': '{{ csrf_token }}'}
        })
        .then(response => response.json())
        .then(data => alert(data.message));
    }
    </script>
</body>
</html>

6. 创建movies/templates/movies/movie_detail.html:

<!DOCTYPE html>
<html>
<head>
    <title>{{ movie.title }}</title>
    <style>
        .player-container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        video {
            width: 100%;
            border-radius: 8px;
        }
    </style>
</head>
<body>
    <div class="player-container">
        <h1>{{ movie.title }}</h1>
        
        <!-- 使用HTML5 video标签播放 -->
        <video controls autoplay>
            <source src="{{ movie.play_url }}" type="video/mp4">
            您的浏览器不支持视频播放
        </video>
        
        <!-- 或者使用第三方播放器(如DPlayer) -->
        <!-- 
        <div id="dplayer"></div>
        <script src="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js"></script>
        <script>
            const dp = new DPlayer({
                container: document.getElementById('dplayer'),
                video: {
                    url: '{{ movie.play_url }}'
                }
            });
        </script>
        -->
        
        <div class="movie-description">
            <h3>电影描述</h3>
            <p>{{ movie.description }}</p>
        </div>
    </div>
</body>
</html>

7. 配置URLs:

# movie_project/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('movies.urls')),
]

# movies/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.MovieListView.as_view(), name='movie_list'),
    path('movie/<int:pk>/', views.MovieDetailView.as_view(), name='movie_detail'),
    path('start-crawl/', views.start_crawl, name='start_crawl'),
]

8. 运行项目:

# 迁移数据库
python manage.py makemigrations
python manage.py migrate

# 运行服务器
python manage.py runserver

关键点说明:

  1. 爬虫部分需要根据实际目标网站调整解析逻辑
  2. 播放功能使用HTML5原生video标签,支持MP4等格式
  3. 可以集成DPlayer等第三方播放器获得更好体验
  4. 爬虫启动使用异步执行,避免阻塞Web请求

总结: 这个方案实现了完整的电影爬取、存储、展示和播放流程,核心是爬虫数据采集和Django的MVC架构。

是吗 0.0
以前用的 Video.js 播放器,刚改到 flowplayer 的…

哈哈哈这个轮子我造过

好像把 Chrome 设置允许网站使用 Flash 就可以了,默认好像是先询问

这个项目不错!

我挂代理能访问 ipv6.google.com 和北邮人,但访问不了 http://hdtv.neu6.edu.cn/ ,是限制了什么么?

ip 限制

限制国外 IP ?

所以还是要走流量。学生党还是继续使用 ipv6 好了

chrome 下还是无法播放

很卡、、、、

手机 chrome 上全是唧唧声,电影的正常声音听不到




看来 flowplayer 兼容性不太好,有时间换回 Video.js ,或者你们推荐个好用的播放器?

打不开啊~~~

回到顶部