python scrapy爬虫练习(1) 爬取豆瓣电影top250信息

2021-01-23 13:36:44 浏览数 (1)

文章目录

一、分析网页

目标URL:https://movie.douban.com/top250?start=0&filter=

每一页有25条电影信息,总共10页。检查网页可以发现,每条电影的详细信息在 ol class=“grid_view” 下的 li 标签里。

翻页查看网页可以发现URL变化的规律,在第几页,URL为:f’https://movie.douban.com/top250?start={(page-1) * 25} &filter=’

在写scrapy爬虫时,构造出10页的URL,生成10次请求。

二、scrapy爬虫

编写scrapy爬虫,电影信息保存到csv文件,电影海报保存到本地文件夹。

创建项目

代码语言:txt复制
scrapy startproject Douban_movie_top250
cd Douban_movie_top250
scrapy genspider Douban movie.douban.com

构造请求

Douban.py中定义 start_requests() 方法,爬取十页的电影信息,生成10次请求,代码如下:

代码语言:txt复制
    def start_requests(self):
        for i in range(10):
            url = f'https://movie.douban.com/top250?start={25 * i}&filter='
            yield Request(url=url, callback=self.parse)

编写 items.py

代码语言:txt复制
import scrapy


class DoubanMovieTop250Item(scrapy.Item):
    name = scrapy.Field()
    pic_link = scrapy.Field()
    rank = scrapy.Field()
    director_actor = scrapy.Field()
    info = scrapy.Field()
    rating_score = scrapy.Field()
    rating_num = scrapy.Field()
    introduce = scrapy.Field()

编写 Douban.py

Spider类定义了如何爬取某个(或某些)网站,包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(抓取item)

代码语言:txt复制
import scrapy
from scrapy import Request
from Douban_movie_top250.items import DoubanMovieTop250Item


class DoubanSpider(scrapy.Spider):
    name = 'Douban'
    allowed_domains = ['movie.douban.com']

    def start_requests(self):
        for i in range(10):
            url = f'https://movie.douban.com/top250?start={25 * i}&filter='
            yield Request(url=url, callback=self.parse)

    def parse(self, response, **kwargs):
        for li in response.xpath("//ol[@class='grid_view']/li"):
            item = DoubanMovieTop250Item()
            item['rank'] = li.xpath(".//div[@class='pic']/em/text()").extract_first()
            item['name'] = li.xpath(".//div[@class='hd']/a/span[@class='title']/text()").extract_first()
            item['pic_link'] = li.xpath(".//div[@class='pic']/a/img/@src").extract_first()
            item['info'] = li.xpath(".//div[@class='bd']/p/text()").extract()[1].strip()
            item['director_actor'] = li.xpath(".//div[@class='bd']/p/text()").extract_first().strip()
            item['rating_score'] = li.xpath(".//div[@class='star']/span[2]/text()").extract_first()
            item['rating_num'] = li.xpath(".//div[@class='star']/span[4]/text()").extract_first()
            item['introduce'] = li.xpath(".//p[@class='quote']/span/text()").extract_first()
            yield item

编写管道文件 pipelines.py

还要将电影海报一起下载下来,所以需要编写管道文件 pipelines.py,Scrapy 提供了专门处理下载的 Pipeline,包括文件下载和图片下载。下载文件和图片的原理与抓取页面的原理一样,因此下载过程支持异步和多线程,十分高效。

代码语言:txt复制
from scrapy.pipelines.images import ImagesPipeline  # scrapy图片下载器
from scrapy import Request
from scrapy.exceptions import DropItem


class DoubanMovieTop250Pipeline(ImagesPipeline):
    # 请求下载图片
    def get_media_requests(self, item, info):
        yield Request(item['pic_link'], meta={'name': item['name']})

    def item_completed(self, results, item, info):
        # 分析下载结果并剔除下载失败的图片
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        return item

    # 重写file_path方法,将图片以原来的名称和格式进行保存
    def file_path(self, request, response=None, info=None):
        name = request.meta['name']  # 接收上面meta传递过来的图片名称
        file_name = name   '.jpg'    # 添加图片后缀名
        return file_name

配置文件 settings.py

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

BOT_NAME = 'Douban_movie_top250'

SPIDER_MODULES = ['Douban_movie_top250.spiders']
NEWSPIDER_MODULE = 'Douban_movie_top250.spiders'

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 10

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 0.25

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'Douban_movie_top250.pipelines.DoubanMovieTop250Pipeline': 300,
}
IMAGES_STORE = './Douban_pic'

运行程序

代码语言:txt复制
# 切换路径到img_spider的目录
scrapy crawl Douban -o movies_info.csv

运行效果如下:

scrapy爬虫在 2020-08-28 16:56:14启动,输出了 Scrapy的版本和一些配置信息,之后爬虫一边爬取一边下载,下载速度非常快。

2020-08-28 16:56:45 scrapy爬虫完成抓取。

运行结果如下:

三、处理数据

用scrapy框架爬取电影信息时,支持异步、并发,爬取效率很高,但输出到CSV文件里列名并没有按照 item 赋值时的顺序,每行的电影信息页没有按照排名排序,将数据处理一下并重新保存到Excel。

代码语言:txt复制
import pandas as pd


df4 = pd.read_csv('movies_info.csv')
cols = df4.columns[[5, 3, 0, 1, 6, 7, 2, 4]]  # 交换列的位置  自定义
new_df4 = df4[cols]
new_df4.sort_values(by='rank', inplace=True)  # 按排名排序
new_df4.to_excel('moives_info.xlsx', index=False)   # 重新保存到Excel

运行效果如下:

作者:叶庭云 微信公众号:修炼Python CSDN:https://yetingyun.blog.csdn.net/ 本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。 觉得文章对你有帮助、让你有所收获的话,期待你的点赞呀,不足之处,也可以在评论区多多指正。

0 人点赞