【python可视化】爬取豆瓣电影Top250(附源码)

news2024/10/7 15:22:21

前言

        在网络爬虫的开发过程中,经常会遇到需要处理一些反爬机制的情况。其中之一就是网站对于频繁访问的限制,即IP封禁。为了绕过这种限制,我们可以使用代理IP来动态改变请求的来源IP地址。在本篇博客中,将介绍如何使用代理IP的技术来爬取某瓣电影排行榜,并将结果写入Excel文件。

准备工作

首先,我们需要准备以下环境和工具:

  • Python编程语言

  • requests库:用于发送HTTP请求

  • BeautifulSoup库:用于解析HTML页面

  • openpyxl库:用于操作Excel文件

  • 一个可用的代理IP池

步骤

1. 获取代理IP

        使用搜索引擎搜索"免费代理IP",找到一个可用的代理IP网站。请注意,不同的网站可能有不同的获取代理IP的方式。你需要根据特定网站的规则来获取代理IP列表。

使用IP代理的必要性:

  1. 隐藏真实的访问源,保护个人或机构的隐私和安全。

  2. 绕过目标网站的访问限制,如IP封禁、地区限制等。

  3. 分散访问压力,提高爬取效率和稳定性。

  4. 收集不同地区或代理服务器上的数据,用于数据分析和对比。

爬虫是一种通过自动化方式从网站上获取数据的程序,而代理IP则是用于隐藏真实IP地址的中间服务器。

        IP代理和爬虫的关系?

        当你使用爬虫程序时,你的请求会发送到目标网站,并且网站可以看到你的真实IP地址。然而,如果你频繁地发送请求,可能会导致你的IP地址被封锁或限制访问。为了解决这个问题,可以使用代理IP。

        代理IP充当了一个中间服务器的角色,将你的请求通过不同的IP地址发送到目标网站。这样,目标网站只能看到代理IP的地址,而不是你的真实IP地址。通过使用不同的代理IP轮换发送请求,可以减少被封锁或限制访问的风险。

        另外,代理IP还可以用于绕过地理限制。有些网站或服务可能根据用户所在地区提供不同的内容或限制访问。通过使用代理IP,你可以模拟不同地区的访问,以便获取特定地区的数据。

2. 验证代理IP的可用性

        将获取的代理IP列表保存到一个文件中(例如proxies.txt),然后编写代码来验证这些代理IP是否可用。我们可以通过发送请求到一个公开的IP查询API,来检查代理IP是否有效。

import requests
​
def check_proxy(proxy):
    try:
        response = requests.get("http://ip-api.com/json", proxies={"http": proxy, "https": proxy}, timeout=5)
        if response.status_code == 200:
            return True
    except requests.exceptions.RequestException:
        pass
    return False
​
with open("proxies.txt", "r") as f:
    proxies = f.read().splitlines()
​
valid_proxies = []
for proxy in proxies:
    if check_proxy(proxy):
        valid_proxies.append(proxy)
​
print(valid_proxies)

3. 爬取某瓣电影排行榜

        使用valid_proxies中的代理IP,编写代码来发送HTTP请求并解析网页内容。我们可以使用BeautifulSoup库来解析HTML页面,并提取所需的信息。

        导入模块:

        代码导入了所需要的库,包括re用于正则表达式操作,pandas用于写入Excel文件,requests用于发送HTTP请求,lxml用于解析HTML网页内容,time用于延时操作。

import re # 正则
import pandas as pd # pandas,写入Excel文件
import requests
from lxml import etree
import time 

        定义函数get_html_str(url),该函数用于发送HTTP请求并获取响应内容。函数中设置了请求头模拟浏览器,并可以添加代理IP进行请求。最后返回网页源码。

        

def get_html_str(url):
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'}

    proxies = {
        "http": "自己填一下子",
    }
    # 添加请求头和代理IP发送请求
    response = requests.get(url, headers=headers, proxies=proxies)  #
    # 获取网页源码
    html_str = response.content.decode()
    # 返回网页源码
    return html_str

        定义函数get_data(html_str, data_list),该函数用于从网页源码中提取数据并存入列表。函数使用lxml将网页源码转换为Elements对象方便后续使用XPath进行解析。通过XPath取到所有的li标签,然后遍历每个li标签,利用XPath获取每个字段的信息,例如排名、电影名、评分等,并使用正则表达式进行字符串的提取和处理,最后将数据存入列表。

def get_data(html_str, data_list):
    """提取数据写入列表"""
    # 将html字符串转换为etree对象方便后面使用xpath进行解析
    html_data = etree.HTML(html_str)
    # 利用xpath取到所有的li标签
    li_list = html_data.xpath("//ol[@class='grid_view']/li")
    # 打印一下li标签个数看是否和一页的电影个数对得上
    print(len(li_list))  # 输出25,没有问题
    # 遍历li_list列表取到某一个电影的对象
    for li in li_list:
        # 用xpath获取每一个字段信息
        # 排名
        ranking = li.xpath(".//div[@class='pic']/em/text()")[0]
        # 电影名
        title = li.xpath(".//div[@class='hd']/a/span[1]/text()")[0]
        # 评分
        score = li.xpath(".//span[@class='rating_num']/text()")[0]
        # 评价人数
        evaluators_number = li.xpath(".//div[@class='star']/span[4]/text()")[0]
        evaluators_number = evaluators_number.replace('人评价', '')  # 将'人评价'替换为替换为空,更美观
        # 导演、主演
        str1 = li.xpath(".//div[@class='bd']/p[1]//text()")[0]
        # 利用正则提取导演名
        try:
            director = re.findall("导演: (.*?)主演", str1)[0]
            director = re.sub('\xa0', '', director)
        except:
            director = None
        # 利用正则提取主演
        try:
            performer = re.findall("主演: (.*)", str1)[0]
            performer = re.sub('\xa0', '', performer)
        except:
            performer = None
        # 上映时间、制片国家、电影类型都在这里标签下
        str2 = li.xpath(".//div[@class='bd']/p[1]//text()")[1]
        #
        try:
            # 通过斜杠进行分割
            str2_list = str2.split(' / ')
            # 年份
            year = re.sub('[\n ]', '', str2_list[0])
            # 制片国家
            country = str2_list[1]
            # 影片类型
            type = re.sub('[\n ]', '', str2_list[2])
        except:
            year = None
            country = None
            type = None
        url = li.xpath(".//div[@class='hd']/a/@href")[0]
        print({'排名': ranking, '电影名': title, '评分': score, '评价人数': evaluators_number, '导演': director,
               '主演': performer, '年份': year, '制片国家': country, '影片类型': type, '影片主页链接': url})
        data_list.append(
            {'排名': ranking, '电影名': title, '评分': score, '评价人数': evaluators_number, '导演': director,
             '主演': performer, '年份': year, '制片国家': country, '影片类型': type, '影片主页链接': url})

        定义函数into_excel(data_list),该函数用于将数据列表写入Excel文件。首先创建一个DataFrame对象,然后使用to_excel()方法将DataFrame写入Excel文件。

       

def into_excel(data_list):
    # 创建DataFrame对象
    df = pd.DataFrame(data_list)
    # 写入excel文件
    df.to_excel('电影Top250排行.xlsx')

        定义了一个主函数main(),该函数用于控制流程。在主函数中,设置了翻页,循环遍历10页的数据。通过拼接URL,调用get_html_str()函数获取网页源码,然后调用get_data()函数提取数据,并将数据存入列表。为了控制爬取速度,使用time.sleep()方法进行延时操作。最后调用into_excel()函数将数据列表写入Excel文件。

        


def main():
    data_list = []  # 空列表用于存储每页获取到的数据
    # 1. 设置翻页
    for i in range(10):
        url = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter='
        # 2. 获取网页源码
        html_str = get_html_str(url)
        # 3. 提取数据
        get_data(html_str, data_list)
        # 4. 限制爬取的速度
        time.sleep(5)
    # 5. 写入excel
    into_excel(data_list)


if __name__ == "__main__":
    main()

最终效果图

         完整代码如下:

        

import re # 正则
import pandas as pd # pandas,写入Excel文件
import requests
from lxml import etree
import time 


def get_html_str(url):
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'}

    proxies = {
        "http": "自己填一下子",
    }
    # 添加请求头和代理IP发送请求
    response = requests.get(url, headers=headers, proxies=proxies)  #
    # 获取网页源码
    html_str = response.content.decode()
    # 返回网页源码
    return html_str


def get_data(html_str, data_list):
    """提取数据写入列表"""
    # 将html字符串转换为etree对象方便后面使用xpath进行解析
    html_data = etree.HTML(html_str)
    # 利用xpath取到所有的li标签
    li_list = html_data.xpath("//ol[@class='grid_view']/li")
    # 打印一下li标签个数看是否和一页的电影个数对得上
    print(len(li_list))  # 输出25,没有问题
    # 遍历li_list列表取到某一个电影的对象
    for li in li_list:
        # 用xpath获取每一个字段信息
        # 排名
        ranking = li.xpath(".//div[@class='pic']/em/text()")[0]
        # 电影名
        title = li.xpath(".//div[@class='hd']/a/span[1]/text()")[0]
        # 评分
        score = li.xpath(".//span[@class='rating_num']/text()")[0]
        # 评价人数
        evaluators_number = li.xpath(".//div[@class='star']/span[4]/text()")[0]
        evaluators_number = evaluators_number.replace('人评价', '')  # 将'人评价'替换为替换为空,更美观
        # 导演、主演
        str1 = li.xpath(".//div[@class='bd']/p[1]//text()")[0]
        # 利用正则提取导演名
        try:
            director = re.findall("导演: (.*?)主演", str1)[0]
            director = re.sub('\xa0', '', director)
        except:
            director = None
        # 利用正则提取主演
        try:
            performer = re.findall("主演: (.*)", str1)[0]
            performer = re.sub('\xa0', '', performer)
        except:
            performer = None
        # 上映时间、制片国家、电影类型都在这里标签下
        str2 = li.xpath(".//div[@class='bd']/p[1]//text()")[1]
        #
        try:
            # 通过斜杠进行分割
            str2_list = str2.split(' / ')
            # 年份
            year = re.sub('[\n ]', '', str2_list[0])
            # 制片国家
            country = str2_list[1]
            # 影片类型
            type = re.sub('[\n ]', '', str2_list[2])
        except:
            year = None
            country = None
            type = None
        url = li.xpath(".//div[@class='hd']/a/@href")[0]
        print({'排名': ranking, '电影名': title, '评分': score, '评价人数': evaluators_number, '导演': director,
               '主演': performer, '年份': year, '制片国家': country, '影片类型': type, '影片主页链接': url})
        data_list.append(
            {'排名': ranking, '电影名': title, '评分': score, '评价人数': evaluators_number, '导演': director,
             '主演': performer, '年份': year, '制片国家': country, '影片类型': type, '影片主页链接': url})


def into_excel(data_list):
    # 创建DataFrame对象
    df = pd.DataFrame(data_list)
    # 写入excel文件
    df.to_excel('电影Top250排行.xlsx')


def main():
    data_list = []  # 空列表用于存储每页获取到的数据
    # 1. 设置翻页
    for i in range(10):
        url = 'https://movie.douban.com/top250?start=' + str(i * 25) + '&filter='
        # 2. 获取网页源码
        html_str = get_html_str(url)
        # 3. 提取数据
        get_data(html_str, data_list)
        # 4. 限制爬取的速度
        time.sleep(5)
    # 5. 写入excel
    into_excel(data_list)


if __name__ == "__main__":
    main()

总结

        通过使用代理IP技术,我们可以绕过网站的IP封禁限制,成功爬取某瓣电影排行榜的信息,并将结果写入Excel文件。这样,我们就可以方便地对电影信息进行整理和分析了。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/870739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【第二阶段】在函数中定义参数是函数的函数

1.理解:在一个函数中有一个参数a,这个参数a又属于一个函数,a即时参数又是函数 2.用kotlin实现登录 /*** You can edit, run, and share this code.* play.kotlinlang.org*/ fun main() {//调用传参//普通参数传入即可,针对在调用函数中的参数函数传入使用…

Leetcode34 在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 代码: c…

SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP

SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP 本文是SpringBoot第35讲,主要介绍数据库连接池,以及SpringBoot集成默认的HikariCP的实践。 文章目录 SpringBoot第35讲:SpringBoot集成连接池 - 默认连接池HikariCP1…

【STM32】简介

🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星T…

Exploiting Proximity-Aware Tasks for Embodied Social Navigation 论文阅读

论文信息 题目:Exploiting Proximity-Aware Tasks for Embodied Social Navigation 作者:Enrico Cancelli, Tommaso Campari 来源:arXiv 时间:2023 Abstract 学习如何在封闭且空间受限的室内环境中在人类之间导航&a…

StarGANv2: Diverse Image Synthesis for Multiple Domains论文解读及实现

StarGAN v2: Diverse Image Synthesis for Multiple Domainsp github:https://github.com/clovaai/stargan-v2 0 小结 0.1 模型 4个 模型四个: Generator: G网络 输入图片x,和风格编码s(可以是F网络或者E网络生成的s&#xff…

LeetCode 778. Swim in Rising Water【最小瓶颈路;二分+BFS或DFS;计数排序+并查集;最小生成树】2096

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…

城市最短路

题目描述 下图表示的是从城市A到城市H的交通图。从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。 输入输出格式 输入格式: 无 输出格式: 倒序输出经过城市最少的一条路线 输入输出样例 输入样例…

【LeetCode75】第二十七题(933)最近的请求次数

目录 题目: 示例: 分析: 代码运行结果: 题目: 示例: 分析: 首先这是LeetCode75里第一道设计类的题目,这种类型的题目会比较新颖,就是按照题目要求来设计一个类。然后…

GIL 锁或将在 CPython 中成为可选项

哈喽大家好,我是咸鱼 几天前有媒体报道称,经过多次辩论,Python 指导委员会打算批准通过 PEP 703 提案,让 GIL(全局解释器)锁在 CPython 中成为一个可选项 PEP 703 提案主要目标是使 GIL 变成可选项&#…

二叉树的讲解

💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大家三连关注&…

定义行业新标准?谷歌:折叠屏手机可承受20万次折叠

根据Patreon账户上的消息,Android专家Mishaal Rahman透露,谷歌计划推出新的硬件质量标准,以满足可折叠手机市场的需求。Android原始设备制造商(OEM)将需要完成谷歌提供的问卷调查,并提交样品设备进行严格审…

读书笔记 |【项目思维与管理】➾ 顺势而动

读书笔记 |【项目思维与管理】➾ 顺势而动 一、企业步入“终结者时代”二、过去成功的经验也许是最可怕的三、做好非重复性的事四、适应客户是出发点五、向知识型企业转变六、速度是决胜条件 💖The Begin💖点点关注,收藏不迷路💖 …

【C++ 学习 ⑬】- 详解 list 容器

目录 一、list 容器的基本介绍 二、list 容器的成员函数 2.1 - 迭代器 2.2 - 修改操作 三、list 的模拟实现 3.1 - list.h 3.2 - 详解 list 容器的迭代器 3.2 - test.cpp 一、list 容器的基本介绍 list 容器以类模板 list<T>&#xff08;T 为存储元素的类型&…

ruoyi-vue-v3.8.6-搭建

一、准备工作 环境&#xff1a; win10、MySQL8、JDKjdk1.8.0_311 redis6.2.6 IDEA 2022.3.3 maven3.9 Node v18.14.2 npm 9.5.0 版本&#xff1a; 若依框架官方文档&#xff1a;http://doc.ruoyi.vip/ 官网导航&#xff1a;http://120.79.202.7/ 若依项目地址&#xff…

将数组(矩阵)旋转根据指定的旋转角度scipy库的rotate方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将数组(矩阵)旋转 根据指定的旋转角度 scipy库的rotate方法 关于下列代码说法正确的是&#xff1f; import numpy as np from scipy.ndimage import rotate a np.array([[1,2,3,4], …

腾讯云服务器竞价实例是什么?适用于什么行业?有啥优惠?

腾讯云服务器CVM计费模式分为包年包月、按量计费和竞价实例&#xff0c;什么是竞价实例&#xff1f;竞价实例和按量付费相类似&#xff0c;优势是价格更划算&#xff0c;缺点是云服务器实例有被自动释放风险&#xff0c;腾讯云服务器网来详细说下什么是竞价实例&#xff1f;以及…

八、解析应用程序——分析应用程序(1)

文章目录 一、确定用户输入入口点1.1 URL文件路径1.2 请求参数1.3 HTTP消息头1.4 带外通道 二、确定服务端技术2.1 提取版本信息2.2 HTTP指纹识别2.3 文件拓展名2.4 目录名称2.5 会话令牌2.6 第三方代码组件 小结 枚举尽可能多的应用程序内容只是解析过程的一个方面。分析应用程…

Leetcode35 搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 解析&#xff1a;以示例2来举例&#xff0c;left 0,right 3,mid 1…

【CSS】CSS 布局——弹性盒子

Flexbox 是一种强大的布局系统&#xff0c;旨在更轻松地使用 CSS 创建复杂的布局。 它特别适用于构建响应式设计和在容器内分配空间&#xff0c;即使项目的大小是未知的或动态的。Flexbox 通常用于将元素排列成一行或一列&#xff0c;并提供一组属性来控制 flex 容器内的项目行…