Titan笔记

  • 首页
  • Java
  • 数据结构
  • Web
  • C语言
  • Python
  • 杂谈
  • 逸笔挥墨
Titan笔记
分享学习、研究与开发过程中的点滴记忆
  1. 首页
  2. Python
  3. 正文

Python爬虫获取豆瓣TOP250电影详情

2020年6月23日 284点热度 3人点赞 2条评论

介绍

偶然间看到豆瓣电影的TOP250榜单,于是突发奇想写了这个爬虫脚本。将通过爬取豆瓣电影TOP250的榜单列表获取电影详情页的URL,然后再爬取电影详情页URL中的内容,最终获得电影的名称,导演,演员,类别,制片国家/地区,语言,上映日期,片长和剧情简介等信息,经过一系列的处理后输出。

输出结果

最终结果将输出为JSON形式,为当前运行目录下的result.json,形式如下

代码

import requests
import threading
import re
import queue
import json

# Global HTTP Header Settings
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/78.0.3904.108 Safari/537.36",
}
detailUrls = []
exitFlag = False

jsonResult = []


# Retrieve the detail url
def getDetailUrl(source):
    pattern = r'<div class="hd">[\s]+<a href="(.*?)"'
    matcher = re.compile(pattern, re.S | re.M)
    result = matcher.findall(source)
    return result


# Get the movie details
def getMovieDetail(source):
    # Regex Patterns
    titlePattern = r'v:itemreviewed">(.*?)</span>'
    directorPattern = r'rel="v:directedBy">(.*?)</a>'
    starPattern = r'rel="v:starring">(.*?)</a>'
    categoryPattern = r'property="v:genre">(.*?)</span>'
    countryPattern = r'<span class="pl">制片国家/地区:</span>[\s]+(.*?)<'
    languagePattern = r'<span class="pl">语言:</span>[\s]+(.*?)<'
    releaseTimePattern = r'v:initialReleaseDate".*?>(.*?)</span>'
    runtimePattern = r'v:runtime"[\s]+content="(.*?)"'
    descriptionPattern = r'property="v:summary".*?>[\s]+(.*?)</span>'
    # Match Results
    titleMatch = re.search(titlePattern, source, re.S | re.M)
    directorMatch = re.findall(directorPattern, source, re.S | re.M)
    starMatch = re.findall(starPattern, source, re.S | re.M)
    categoryMatch = re.findall(categoryPattern, source, re.S | re.M)
    countryMatch = re.search(countryPattern, source, re.S | re.M)
    languageMatch = re.search(languagePattern, source, re.S | re.M)
    releaseTimeMatch = re.findall(releaseTimePattern, source, re.S | re.M)
    runtimeMatch = re.search(runtimePattern, source, re.S | re.M)
    descriptionMatch = re.search(descriptionPattern, source, re.S | re.M)
    # Build the Result Dict
    try:
        result = {
            "num": "",
            "title": titleMatch.group(1),
            "director": "/".join(directorMatch),
            "stars": "/".join(starMatch),
            "category": "/".join(categoryMatch),
            "country": countryMatch.group(1),
            "language": languageMatch.group(1),
            "release_time": "/".join(releaseTimeMatch),
            "runtime": runtimeMatch.group(1),
            "description": re.sub(r'[\s]{3,}', "", descriptionMatch.group(1))  # Delete the blanks
        }
        return result
    except Exception as e:
        return None


# Fetch the movie details from the detail url
def fetchDetails(detailUrl):
    r = requests.get(url=detailUrl, headers=headers, timeout=15)
    result = getMovieDetail(r.text)
    return result


# Fetch the movie list information
def fetchPage(startRecord):
    targetUrl = "https://movie.douban.com/top250?start=" + str(startRecord)
    r = requests.get(url=targetUrl, headers=headers, timeout=15)
    urlList = getDetailUrl(r.text)
    count = startRecord
    for detailUrl in urlList:
        with lock:
            count += 1
            detailUrls.append({"num": count, "url": detailUrl})
    pass


def detailJob():
    while not q.empty():
        target = q.get()
        targetUrl = target['url']
        targetNum = target['num']
        result = fetchDetails(targetUrl)
        if result is not None:
            result['num'] = targetNum
            jsonResult.append(result)
        pass


if __name__ == '__main__':
    lock = threading.Lock()
    q = queue.Queue()
    threadList = []
    # Create and Start the fetch page job
    print("Create and Start the fetch page job")
    page = 0
    for i in range(10):
        t = threading.Thread(target=fetchPage, args=(page,))
        threadList.append(t)
        t.start()
        page += 25
        pass
    for t in threadList:
        t.join()
        pass
    threadList.clear()
    print("Fetch detail urls finished")
    for url in detailUrls:
        q.put(url)
    # Create and Start the fetch details job
    print("Start to fetch details")
    for i in range(10):
        t = threading.Thread(target=detailJob)
        threadList.append(t)
        t.start()
    for t in threadList:
        t.join()
        pass
    print("Fetch Details Finished")
    print("Start to Write Data")
    jsonResult.sort(key=lambda x: x['num'])
    with open("result.json", "a+", encoding="utf-8") as fo:
        fo.write(json.dumps(jsonResult, indent=2, ensure_ascii=False))
    print("Over")
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: Python Python爬虫
最后更新:2020年6月23日

Titan

兴趣广泛而无一精擅
想到什么,我总是渴望以代码的方式去呈现
永远年轻,永远热泪盈眶
Stay Hungry, Stay Foolish

点赞
< 上一篇

文章评论

  • 阿sir不是吧

    感觉可以用BeautifulSoup来做,这样做出来的代码可能还稍微简洁一些

    2020年9月18日
    回复
    • Titan

      @阿sir不是吧 习惯了使用正则表达式来匹配,当然用BS也是完全可以的,个人习惯使然。

      2020年9月20日
      回复
  • 取消回复

    Titan

    兴趣广泛而无一精擅
    想到什么,我总是渴望以代码的方式去呈现
    永远年轻,永远热泪盈眶
    Stay Hungry, Stay Foolish

    逸笔挥墨 - Titan的文学天地
    文章分类
    • C语言 (4)
    • Hadoop (1)
    • Hive (3)
    • Java (16)
    • JavaWeb (3)
    • Linux运维之道 (1)
    • Mybatis学习笔记 (3)
    • Python (3)
    • SpringCloud (1)
    • Web (5)
    • Web前端 (4)
    • Web后端 (5)
    • 数据库 (1)
    • 数据结构 (10)
    • 杂谈 (3)
    • 诗词歌赋 (1)
    • 随摘 (2)
    最新 热点 随机
    最新 热点 随机
    关于我和Titan笔记 Spring Cloud 微服务学习笔记 - 开篇 TitanEMS - Titan企业员工管理系统 - JavaWeb期末实践项目 Linux 网络优化指南 - 改善Linux的网络性能 关于Hive使用的一些实例 Apache-Hive 使用MySQL存储Hive的元数据
    Spring Cloud 微服务学习笔记 - 开篇TitanEMS - Titan企业员工管理系统 - JavaWeb期末实践项目2021年1月随摘2021年1月诗摘关于我和Titan笔记《梦之浮桥》中的几句
    [数据结构] 队列的链式存储实现 [Python]随机生成大量的虚拟信息测试数据(姓名,手机号,ID,家庭住址等) [Java] 在Java中优雅地进行文件IO操作 Spring与Mybatis的整合 Titan商店 - 又一个Web静态项目 [数据结构] 稀疏矩阵的存储
    标签聚合
    二叉树 Apache-Hive 数据结构 Mybatis学习笔记 PHP框架 链式存储 Java Python
    友情链接
    • Mttblog

    COPYRIGHT © 2016 - 2021 Titan笔记. ALL RIGHTS RESERVED.

    THEME KRATOS MADE BY VTROIS

    豫ICP备20001822号-1

    豫公网安备 41010502004418号