Scrapy爬取豆瓣电影Top250

这两天摸索了下scrapy,刚看文档的时候觉得有点生无可恋,scrapy框架个人还是觉得比较难懂的,需要学习的地方非常多,之前用beautifulsoup4爬过top250,比scrapy简单更容易理解!!

Scrapy简介

Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。 下面对每个组件都做了简单介绍,数据流如下所描述。


image
  • Scrapy Engine
    引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。 详细内容查看下面的数据流(Data Flow)部分
  • 调度器(Scheduler)
    调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎
  • 下载器(Downloader)
    下载器负责获取页面数据并提供给引擎,而后提供给spider
  • Spiders
    Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每 个spider负责处理一个特定(或一些)网站
  • Item Pipeline
    Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数 据库中)
  • 下载器中间件(Downloader middlewares)
    下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的 response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能
  • Spider中间件(Spider middlewares)
    Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出 (items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能
  • 数据流(Data flow)
    Scrapy中的数据流由执行引擎控制,其过程如下:

引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个要爬取的 URL(s)。
引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度。
引擎向调度器请求下一个要爬取的URL。
调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求(request)方向)转发给下载 器(Downloader)。
一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方 向)发送给引擎。
引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。
Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。
引擎将(Spider返回的)爬取到的Item给Item Pipeline,将(Spider返回的)Request给调度器。
(从第二步)重复直到调度器中没有更多地request,引擎关闭该网站

scrapy的流程如图,并且可归纳如下

  • 首先下载器下载request回执的html等的response
  • 然后下载器传给爬虫解析
  • 接着爬虫解析后交给调度器过滤,查重等等
  • 最后交给管道,进行爬取数据的处理

建议大家参考下中文版的Scrapy文档,看文档还是比较枯燥的,Scrapy又比较难懂(大神忽略),务必要有耐心!!!!!!

实战应用

首先下载Scrapy包

pip install scrapy

这样安装,windows平台应该是会报错的,我当时装Scrapy时废了很大劲才弄完。安装过程中Pycharm或者官网上找不到的模块可以上这个网址找Unofficial Windows Binaries for Python Extension Packages
Pywin32

接着,我们打开CMD,新建一个爬虫文件

scrapy startproject douban

image

C:\Users\ssaw\douban>tree /f
C:.
│ scrapy.cfg

└─douban
│ items.py
│ middlewares.py
│ pipelines.py
│ settings.py
init.py

└─spiders
init.py

简单介绍下这些文件

  • scrapy.cfg: 项目的配置文件
  • douban/: 该项目的python模块。之后您将在此加入代码
  • douban/items.py: 项目中的item文件
  • douban/pipelines.py: 项目中的pipelines文件
  • douban/settings.py: 项目的设置文件
  • douban/spiders/:放置spider代码的目录

编辑items.py文件

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    movie_name = scrapy.Field()
    movie_star = scrapy.Field()
    movie_quote = scrapy.Field()
  • 首先,引入Scrapy
  • 接着,创建一个类,继承自scrapy.item,这个是用来储存要爬下来的数据的存放容器,类似orm的写法
  • 我们要记录的是:电影的名字、电影的评分、电影的引述(quote)

现在,我们在spiders文件夹下创建douban_spider.py
在我们编写爬虫之前,先了解一下scrapy的爬取机制,scrapy提取数据有自己的一套机制。它们被称作选择器(seletors),因为他们通过特定的 XPath 或者 CSS 表达式来“选择” HTML文件中的某个部分。
之前我在博客上也总结过一篇使用Xpath模拟登陆GitHub有兴趣可以看一下
附上Xpath学习教程Xpath

获取网页数据

打开Chrome(F12),查找元素
豆瓣电影TOP250

image

红框圈出来的分别代表

movie_name = div[@class="hd"]/a/span/
movie_star = div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]
movie_quote = div[@class="bd"]/p[@class="quote"]/span[@class="inq"]

# _*_ coding=utf-8 _*_

from scrapy.spiders import Spider
from scrapy.selector import Selector

class DouBanSpider(Spider):
    name = 'db'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # print(response.body)
        selector = Selector(response)

        # print(selector)
        movies = selector.xpath('//div[@class="info"]')
        for movie in movies:
            movie_name = movie.xpath('div[@class="hd"]/a/span/text()').extract()
            movie_star = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()
            movie_quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span[@class="inq"]/text()').extract()


            print(movie_name)
            print(movie_star)
            print(movie_quote)

我们打开setting.py,加上U-A

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'

在CMD中输入scrapy crawl db,运行如下:


image

我们还可以在douban文件根目录创建一个main.py,这样就可以在Pycharm中运行了

from scrapy import cmdline
cmdline.execute("scrapy crawl db".split())

使用Item

Item对象是自定义的python字典。 您可以使用标准的字典语法来获取到其每个字段的值。(字段即是我们之前用Field赋值的属性),Spider将会将爬取到的数据以 Item 对象返回。

item = DoubanItem()

item['movie_name'] = movie_name
item['movie_star'] = movie_star
item['movie_quote'] = movie_quote

好了,现在我们先试着爬取单页面,查看下结果后,再去爬取多页面

from scrapy.spiders import Spider
from scrapy.selector import Selector
from douban.items import DoubanItem



class DouBanSpider(Spider):
    name = 'db'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # print(response.body)
        selector = Selector(response)

        # print(selector)
        movies = selector.xpath('//div[@class="info"]')
        for movie in movies:
            movie_name = movie.xpath('div[@class="hd"]/a/span/text()').extract()
            movie_star = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').extract()
            movie_quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span[@class="inq"]/text()').extract()

            #print(movie_name)
            #print(movie_star)
            #print(movie_quote)

            item = DoubanItem()

            item['movie_name'] = movie_name
            item['movie_star'] = movie_star
            item['movie_quote'] = movie_quote
            yield item
            print(movie_name)
            print(movie_star)
            print(movie_quote)
  • 首先,我们先从scrapy中获得所需要的通用的 spider和 selector
  • 接着,我们使用Item将爬取的数据返回
  • 创建了一个DouBanSpider,继承了 scrapy.Spider 类, 且定义以下三个属性:
  1. name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字
  2. start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一, 后续的URL则从初始的URL获取到的数据中提取。
  3. parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象
  • seletor的方法返回后一定要用它的 extract()方法,来返回一个列表 ;extract()文档的定义:串行化并将匹配到的节点返回一个unicode字符串列表。 结尾是编码内容的百分比
  • 接着,我们把得到的数据保存在Item中
  • 最后,我们使用Feed exports来保存数据
  • 这里使用了yield生成器函数,生成器函数和迭代器有密切关系,也并不是很容易理解,这一点需要多多学习
#看一个yield函数的示例
#函数在每次循环时都会产生一个值,之后将其返回给它的调用者
#函数不断的生成数字的平方

def gensquares(N):
    for i in range(N):
        yield i ** 2
        
for i in gensquares(5):
    print(i, end=' ')

0 1 4 9 16 

好了,spider暂时写完了,我们试着运行下

scrapy crawl db -o douban.json -t json

-o 后面是导出文件名,-t 后面是导出类型。
然后来看一下导出的结果,Pycharm打开json文件即可


image

打印出来的内容需要编码
我们换种方式,把文件格式保存为CSV,使用EXCEL打开

scrapy crawl db -o douban.csv -t csv

image

用excel打开后假如是一堆乱码,就使用记事本打开,把它“另存为”时,编码选择ANSI


image

好了,现在我们添加多页面链接,完整地把TOP250爬取下来
我们从Elements中找到翻页lianjie


image
next_page =response.selector.xpath('//span[@class="next"]/link/@href').extract()
if next_page:
    next_page = next_page[0]
    print(next_page)
    yield Request(self.url + next_page, callback=self.parse)

CMD输入scrapy crawl db -o douban.csv -t csv ,开始运行


image

学习Scrapy需要反复查看文档、资料,这是个简单的学习总结,这两天准备再去学习MongoDB数据库,大家一起加油!!

参考链接
参考链接
Scrapy文档
GitHub
简书
最后,欢迎大家访问我的博客Treehl的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • scrapy学习笔记(有示例版) 我的博客 scrapy学习笔记1.使用scrapy1.1创建工程1.2创建爬虫模...
    陈思煜阅读 12,587评论 4 46
  • Scrapy介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信...
    JasonDing阅读 122,326评论 15 126
  • 天的那边,雏阳高照 海的远边,酒雨纷纷 绵绵丝雨,悠悠我心 徐徐清风,柔柔抚心 半载未归,思之如狂 长相思情,转难入梦
    南国梓桐君阅读 249评论 0 1
  • 成功的时候,谁都是朋友。但只有母亲——她是失败时的伴侣。 感谢妈妈: 自己活了二十多年,最需要感谢的就是母亲。我很...
    宋东珂_阅读 358评论 0 2
  • 一、释运气 运气,是五运六气的简称。 五运:金、木、水、火、土。(行的东西代表)十天干➕阴阳干 六气:太阳寒水、厥...
    王胖胖摇啊摇阅读 1,463评论 1 3