前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >休闲时光:最近上映的电影与爬虫世界,带您彻底放松!

休闲时光:最近上映的电影与爬虫世界,带您彻底放松!

作者头像
AirPython
发布2023-08-22 08:22:51
1580
发布2023-08-22 08:22:51
举报
文章被收录于专栏:Python 自动化Python 自动化
大家好,我是安果!

周末是与亲朋好友相聚的好时机,可以选择一部大家都喜欢的电影,彻底放松,共同度过一个愉快而难忘的周末

本篇文章将介绍如何使用 Scrapy 爬取最新上映的电影

目标对象:

aHR0cHM6Ly93d3cubWFveWFuLmNvbS8=

1、创建爬虫项目

代码语言:javascript
复制
# 创建一个爬虫项目
scrapy startproject film

cd film

# 创建一个爬虫
scrapy genspider maoyan_film https://www.*.com/

2、创建数据表及定义 Item

在数据库中创建一张表用于保存爬取下来的数据

以 Mysql 为例

代码语言:javascript
复制
create table xag.film
(
    id          int auto_increment
        primary key,
    film_name   varchar(100) null,
    show_time   varchar(100) null,
    file_type   varchar(100) null,
    actors      varchar(100) null,
    url         varchar(100) null,
    insert_time date         null
);

然后,定义 Item 存储数据对象

代码语言:javascript
复制
# items.py

import scrapy

class FilmItem(scrapy.Item):
    film_name = scrapy.Field()  # 电影名称
    show_time = scrapy.Field()  # 上映时间
    file_type = scrapy.Field()  # 电影类型
    actors = scrapy.Field()  # 电影演员
    url = scrapy.Field()  # 电影URL
    insert_time = scrapy.Field()  # 插入时间(年、月、日)

3、编写爬虫解析主页面

这里以 Selenium 为例,首先创建一个浏览器对象

PS:为了在服务器上运行,这里对 CentOS 做了兼容处理

代码语言:javascript
复制
import scrapy
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
import platform

...
 def parse(self, response):
        chrome_options = Options()

        if platform.system().lower() == 'windows':
            # win
            s = Service(r"C:\work\chromedriver.exe")
            self.browser = webdriver.Chrome(service=s, options=chrome_options)
        else:
            # Centos
            DRIVER_PATH = '/home/drivers/chromedriver'
            s = Service(DRIVER_PATH)
            chrome_options.add_argument('--no-sandbox')
            chrome_options.add_argument('--headless')  # 无头参数
            chrome_options.add_argument('--disable-gpu')
            self.browser = webdriver.Chrome(service=s, options=chrome_options)

        self.browser.implicitly_wait(5)
...

然后,分析网页结构,使用 Xpath 解析最近上映的电影数据

这里提取出电影的名称及上映时间(包含电影详情页面 URL)

代码语言:javascript
复制
...
        url = response.url
        # selenium打开网页
        self.browser.get(url)
        self.browser.maximize_window()

        WebDriverWait(self.browser, 20).until(
            EC.presence_of_element_located((By.XPATH, '//div[@class="movie-grid"]/div[2]//dl'))
        )

        time.sleep(10)

        video_elements = self.browser.find_elements(By.XPATH, '//div[@class="movie-grid"]/div[2]//dl/dd')

        for video_element in video_elements:
            # 电影名称
            film_name = video_element.find_element(By.XPATH, './/div[contains(@class,"movie-title")]').text

            # 上映时间
            show_time = video_element.find_element(By.XPATH, './/div[contains(@class,"movie-rt")]').text.replace(
                "上映",
                "")

            # 详情页面URL
            file_detail_a_element = video_element.find_element(By.XPATH, './/div[@class="movie-item"]/a')
            file_detail_url = file_detail_a_element.get_attribute("href")

            print('film_name:', film_name, ',show_time:', show_time, ",url:", file_detail_url)

            yield Request(file_detail_url, callback=self.parse_detail, headers=self.headers,
                          meta={"film_name": film_name, "show_time": show_time}, dont_filter=True)
...

4、电影详情页面解析

通过上面的步骤,我们可以拿到某一部电影的详情页面 URL

需要注意的是,如果使用 Selenium 直接打开该页面会触发反爬,这里我们需要修改浏览器特征值

代码语言:javascript
复制
...
 def parse_detail(self, response):
        """
        解析子页面
        :param response:
        :return:
        """
        # 应对反爬
        self.browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
                            Object.defineProperty(navigator, 'webdriver', {
                              get: () => undefined
                            })
                            """
        })
...

接着,打开目标页面,爬取电影的类型及演员列表

最后,将数据将存储到 Item 中

代码语言:javascript
复制
...
 self.browser.get(response.url)
        self.browser.maximize_window()

        # 等待加载完成
        WebDriverWait(self.browser, 20).until(
            EC.presence_of_element_located((By.XPATH, '//div[@class="movie-brief-container"]//a[@class="text-link"]'))
        )

        # 获取电影类型
        film_type_elements = self.browser.find_elements(By.XPATH,
                                                        '//div[@class="movie-brief-container"]//a[@class="text-link"]')
        file_type = ''
        for index, film_type_element in enumerate(film_type_elements):
            if len(film_type_elements) >= 2:
                if index != len(film_type_elements) - 1:
                    file_type += film_type_element.text + "|"
                else:
                    file_type += film_type_element.text
            else:
                file_type += film_type_element.text

        # 演员
        celebritys = self.browser.find_elements(By.XPATH,
                                                '//div[@class="celebrity-group"][2]//div[@class="info"]//a[@class="name"]')[
                     :3]
        actors = ''
        for index, celebrity in enumerate(celebritys):
            if len(celebritys) >= 2:
                if index != len(celebritys) - 1:
                    actors += celebrity.text + "|"
                else:
                    actors += celebrity.text
            else:
                actors += celebrity.text

        item = FilmItem()

        item['film_name'] = response.meta.get("film_name", "")
        item['show_time'] = response.meta.get("show_time", "")
        item["file_type"] = file_type
        item["actors"] = actors
        item['url'] = response.url
        item['insert_time'] = date.today().strftime("%Y-%m-%d")

        yield item
...

5、编写数据库管道,将上面的数据存储到数据库表中

代码语言:javascript
复制
from scrapy.exporters import CsvItemExporter
from film.items import FilmItem
import MySQLdb

class MysqlPipeline(object):
    def __init__(self):
        # 链接mysql数据库
        self.conn = MySQLdb.connect("host", "root", "pwd", "xag", charset="utf8", use_unicode=True)
        self.cursor = self.conn.cursor()

    # 数据同步插入到mysql数据库
    def process_item(self, item, spider):
        table_name = ''
        if isinstance(item, FilmItem):
            table_name = 'film'

        # sql语句
        insert_sql = """
            insert into  {}(film_name,show_time,file_type,actors,url,insert_time) values(%s,%s,%s,%s,%s,%s)  
        """.format(table_name)
        params = list()
        params.append(item.get("film_name", ""))
        params.append(item.get("show_time", ""))
        params.append(item.get("file_type", ""))
        params.append(item.get("actors", ""))
        params.append(item.get("url", ""))
        params.append(item.get("insert_time", ""))

        # 执行插入数据到数据库操作
        self.cursor.execute(insert_sql, tuple(params))

        # 提交,保存到数据库
        self.conn.commit()

        return item

    def close_spider(self, spider):
        """释放数据库资源"""
        self.cursor.close()
        self.conn.close()

6、配置爬虫项目 settings.py

在 settings.py 文件中,对下载延迟、默认请求头、下载管道 Pipline等进行配置

代码语言:javascript
复制
# settings.py

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

DOWNLOAD_DELAY = 3

DEFAULT_REQUEST_HEADERS = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Accept-Language': 'en',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
    'Host':'www.host.com'
}

ITEM_PIPELINES = {
   'film.pipelines.MysqlPipeline': 300,
}

7、运行入口

在项目根目录下创建一个文件,用于定义爬虫的运行入口

代码语言:javascript
复制
from scrapy.cmdline import execute
import sys, os

def start_scrapy():
    sys.path.append(os.path.dirname(__file__))
    # 运行单个爬虫
    execute(["scrapy", "crawl", "maoyan_film"])

if __name__ == '__main__':
    start_scrapy()

最后,我们将爬虫部署到服务器,设置定时任务及消息通知

这样我们可以及时获取最近上映的电影,通过电影类型及演员阵容,挑选自己喜欢的电影

文中所有的源码我已经上传到公众号后台,回复关键字 230708 获取完整源码

如果大家有任何疑惑,欢迎在评论区留言!

推荐阅读

如何利用 Selenium 对已打开的浏览器进行爬虫!

如何利用 Playwright 对已打开的浏览器进行爬虫!

最全总结 | 聊聊 Selenium 隐藏浏览器指纹特征的几种方式!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AirPython 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档