python爬虫-图片爬取(豆瓣TOP250)

 视频学习来源:https://www.bilibili.com/video/BV1d54y1g7db?p=12&vd_source=48ab130a9fd6637ca8a3f391d171df23

目的:将TOP250电影图片以电影名称命名保存在本地

一、基本知识点

  • requsets库,建立与网站的连接;
  • BeautifulSoup库,方便处理从网页返回的数据(一般是HTML代码)。

二、大致思路

  1. 获取网页信息(HTML);
  2. 挑选出网页中关于名称和图片地址的信息;
  3. 根据已有信息保存在本地。

三、步骤细分

1.连接网页,并获取网页信息
# 伪造请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0"
}

for i in range(0, 250, 25):
    url = "https://movie.douban.com/top250?start=" + str(i) + "&filter="
    response = requests.get(url, headers=headers,timeout=(3, 7))
    # 判断是否连接成功,失败则退出程序
    if not response.ok:
        sys.exit("请求失败:"+str(response.status_code))
    # print(response.status_code)
    html = response.text

注意事项:

  • 请求头可以在服务器网络中查看
  • html是一个完整的HTML代码
2.从html中过滤出名称和图片的URL地址,并保存在all_titles和all_images_url两个列表中
soup = BeautifulSoup(html, "html.parser")

# 获取top250中所有标题
all_titles_html = soup.findAll("span", attrs={"class": "title"})
char_to_remove = '/'    # 只需要保留中文标题,将包含‘/’的内容过滤
titles = [i.string for i in all_titles_html if char_to_remove not in i.string]  #名称列表获取成功

# 获取top250中与标题对应的图片
all_images = soup.findAll("img", attrs={"width": "100"})    #此时的all_image是一个tag类型
images_url = [i.get('src') for i in all_images]   # 将all中的src提取出来,src的值就是图片的url

使用BeautifulSoup是为了更好的处理html。

注意事项:

  • all_titles_html返回的tag类型列表,需要转化成string类型列表;
  • all_titles_html返回值里包含了电影的原名,不过原名都有一个共同点,含有'/'字符,可以根据这个提出
  • 在html中包含图片URL的是img自闭合标签,不能使用findAll
3.将两个列表合并成一个字典的代码:
Title_Image = dict(zip(all_titles,all_images_url))
 4.保存本地
#创建一个目录,如果已存在则忽略
os.makedirs(path, exist_ok=True) 
with open(f'{path}/{name}.jpg','wb') as f:
    f.write(content)

注意事项:

  • 打开的路径直接是文件夹,你想想,可以对文件夹进行写入操作吗?

完整代码:

import time,sys,os
import requests
from bs4 import BeautifulSoup

# 伪造请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0"
}
# 需要爬取的数量
number = 250

# 获取top250包含所有名称的列表
def getTitle_Image():
    all_titles = []
    all_images_url = []
    for i in range(0, 250, 25):
        url = "https://movie.douban.com/top250?start=" + str(i) + "&filter="
        response = requests.get(url, headers=headers,timeout=(3, 7))
        # 判断是否连接成功,失败则退出程序
        if not response.ok:
            sys.exit("请求失败:"+str(response.status_code))
        # print(response.status_code)
        html = response.text
        soup = BeautifulSoup(html, "html.parser")

        # 获取top250中所有标题
        all_titles_html = soup.findAll("span", attrs={"class": "title"})
        char_to_remove = '/'    # 只需要保留中文标题,将包含‘/’的内容过滤
        titles = [i.string for i in all_titles_html if char_to_remove not in i.string]  #名称列表获取成功

        # 获取top250中与标题对应的图片
        all_images = soup.findAll("img", attrs={"width": "100"})    #此时的all_image是一个tag类型
        images_url = [i.get('src') for i in all_images]   # 将all中的src提取出来,src的值就是图片的url

        # 一次循环只有25条数据,因此要接在之前的数据上
        all_titles += titles
        all_images_url += images_url

    # 将titles与images_url两个列表合并成一个字典,并返回
    Title_Image = dict(zip(all_titles,all_images_url))

    return Title_Image

def saveImage(name,path,content,url):
    if url[-3:] == 'jpg':
        with open(f'{path}/{name}.jpg','wb') as f:
            f.write(content)
        print(f"已将-{name}-保存至[{path}/{name}.jpg]")
    elif url[-4:] == 'jpeg':
        with open(f'{path}/{name}.jpeg', 'wb') as f:
            f.write(content)
        print(f"已将-[{name}-保存至[{path}/{name}.jpeg]")
    elif url[-3:] == 'png':
        with open(f'{path}/{name}.png', 'wb') as f:
            f.write(content)
        print(f"已将-[{name}-保存至[{path}/{name}.png]")
    else:
        print("图片保存失败,请检查图片格式")

if __name__=='__main__':
    path = './douban250image'
    os.makedirs(path, exist_ok=True) #创建一个目录,如果已存在则忽略
    ti = getTitle_Image()
    id = 1 #用于计数
    for title,image_url in ti.items():
        print(f"ID[{id}]", end=' ')
        id+=1
        try:
            response = requests.get(image_url, headers=headers)
            content = response.content
            saveImage(title,path,content,image_url)
            # print(title,image_url)
        except Exception as e:
            print('超时',sep=' ')
            print(e)
            continue
        time.sleep(0.2)

后续可以学习正则匹配、多线程。

代码部分学习了以下博客:

python 爬虫获取图片(一):简单爬取_python爬虫爬取图片-CSDN博客

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是简单的步骤: 1. 安装 scrapy 和 scrapy-redis ```python pip install scrapy scrapy-redis ``` 2. 创建一个 Scrapy 项目 ```python scrapy startproject douban_top250 ``` 3. 在 settings.py 中加入 scrapy-redis 的相关设置 ```python # 使用 scrapy-redis 的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 使用 scrapy-redis 的去重过滤器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 允许暂停、恢复爬虫 SCHEDULER_PERSIST = True # 设置 redis 为 item pipeline ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300 } # 设置 redis 服务器地址和端口号 REDIS_HOST = 'localhost' REDIS_PORT = 6379 ``` 4. 编写 spider ```python # coding:utf-8 import scrapy from scrapy import Request from scrapy_redis.spiders import RedisSpider class DoubanTop250Spider(RedisSpider): """爬取豆瓣电影 Top 250""" name = 'douban_top250' allowed_domains = ['movie.douban.com'] # 在 Redis 中设置起始爬取的 URL redis_key = 'douban:start_urls' def parse(self, response): # 获取电影列表 movie_list = response.css('.grid_view li') for movie in movie_list: # 获取电影名字和详情页 URL title = movie.css('.title::text').extract_first() detail_url = movie.css('.hd a::attr(href)').extract_first() yield Request(detail_url, callback=self.parse_detail, meta={'title': title}) # 获取下一页的链接 next_url = response.css('.next a::attr(href)').extract_first() if next_url: yield Request(next_url, callback=self.parse) def parse_detail(self, response): # 获取电影详情 title = response.meta['title'] score = response.css('.rating_num::text').extract_first() yield {'title': title, 'score': score} ``` 5. 运行 scrapy-redis 爬虫 首先要在终端中启动 redis 服务: ```python redis-server ``` 然后在一个终端中运行 scrapy-redis 爬虫: ```python scrapy runspider douban_top250.py ``` 在另一个终端中向 Redis 中添加起始 URL: ```python redis-cli lpush douban:start_urls https://movie.douban.com/top250 ``` 爬取结果会自动保存到 Redis 数据库中。你可以通过 redis-cli 或者其他 Redis 客户端查看结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值