美文网首页大数据 爬虫Python AI Sql
【爬虫实战】Scrapy爬取猫眼电影

【爬虫实战】Scrapy爬取猫眼电影

作者: loannes | 来源:发表于2019-10-05 19:00 被阅读0次

前言

最近非常热衷于看电影,准备做一个电影方面的数据分析,所以这次爬虫项目练习就做一次猫眼电影吧。

因为本篇文章是接上篇Scrapy框架的安装及入门,结合官方文档进行编写。所以会着大量篇幅在介绍框架的用法以及详细解释。

猫眼电影页面很多,这次练习抓取最简单的榜单页面。

https://maoyan.com/board/7

Get Started

创建项目
scrapy startproject maoyan

可爬取的数据

  • 标题
  • 主演
  • 上映时间
  • 海报地址
  • 评分

创建数据模型Item

import scrapy

class MaoyanItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()  #标题
    stars = scrapy.Field() # 主演
    showtime = scrapy.Field() # 上映时间
    img = scrapy.Field() # 图片地址
    score = scrapy.Field() # 评分

看到这里唯一有疑惑的地方就是这个Field对象了。由于Field对象支持所有类型的值,所以无需像数据库那样为数据类型操心了。简单来说Item类的用法相当于是一个字典,它可以与Dictionary对象相互转换。


开始着手Spider文件

spiders中创建maoyanSpider.py并定义初始化属性

import scrapy

class TestProject(scrapy.Spider):
    name = 'maoyan'
    allow_domains = ['maoyan.com']
    start_urls = ['https://maoyan.com/board/7']

    def parse(self, response):
        self.log(response.url)

  • name :定义spider名字的字符串,一个项目中可以有多个spider。比如一个项目中我可以爬取猫眼的榜单或者评论,可以通过name属性来区分开。

  • allow_domains : 包含了spider允许爬取的域名列表。 当 OffsiteMiddleware(会在后面说明)启用时, 域名不在列表中的URL不会被跟进。

  • start_urls: 如果没有指定特定的URL,Spider会从start_urls中的URL获取数据。

Scrapy提取数据

Scrapy框架支持xpathcss3 两种选择器。

import scrapy

class TestProject(scrapy.Spider):
    name = 'maoyan'
    allow_domains = ['maoyan.com']
    start_urls = ['https://maoyan.com/board/7']

    def parse(self, response):
        movies = response.xpath('//dl[@class="board-wrapper"]//dd')
        
        item = MaoyanItem()
        for movie in movies:
            item['title'] = movie.css('p.name a::text').extract_first()
            item['stars'] = movie.css('p.star::text').extract_first().strip()
            item['showtime'] = movie.css('p.releasetime::text').extract_first().strip()
            item['score'] = movie.css('i.integer::text').extract_first() + movie.css('i.fraction::text').extract_first()
            item['img'] = movie.css('a.image-link img.board-img::attr(data-src)').extract_first()           
            yield item

以上就是爬取数据的部分,其实非常简单。个人比较喜欢用css3来解析,因为他写法比较简洁易读。而且有时候在用xpath的时候会遇到解析不了的情况。

对选择器不熟悉的可以参考以下几篇文章恶补下:
CSS选择器与xpath
爬虫解析库Xpath
CSS3选择器


反爬虫与反反爬虫

由于爬虫的盛行,很多网站都实行了反爬虫策略。这次在爬取猫眼电影的时候也遇到了这种情况。所谓知己知彼,百战不殆,要想克服这道关卡首先得了解反爬虫是什么。
关于反爬虫的知识可以参考这篇文章,里面写的还是很详细而且通俗易懂,强烈推荐:
关于反爬虫看这一篇就够了

通常反爬虫有那么几种基础手段:

  • 封ip 如果一个ip在某时间段内的请求超过阈值就会被认定为爬虫
  • 检测useragent 发现某个用户在某段时间内请求量超过阈值会被认定为爬虫

针对这两种可以用代理ip以及模拟useragent来达到反反爬虫的目的。我们可以自己搭建代理ip池和useragent池,为了节省时间我选择使用fake-useragentproxy_pool库,以后有空了再研究。
安装fake-useragent以及 proxy_pool

& pip install fake-useragent
& git clone git@github.com:jhao104/proxy_pool.git
# 进入proxy_pool目录后
& pip install -r requirements.txt

具体环境配置以及安装查看链接,这里不再说明了

Spider的中间件 ---- Middleware

Spider中间件是介入到Scrapy的spider处理机制的钩子框架,您可以添加代码来处理发送给 Spiders的response及spider产生的item和request。

如果想要修改ip以及useragent,必须涉及到request


新建manager文件夹并创建ProxyPoolManager.py封装proxy_pool的接口

数据库个人使用的是redis,所以端口和官方demo会不一样。

import requests

class ProxyPoolManager(object):
    """docstring for ProxyPoolManager"""
    def get_proxy():
        return requests.get("http://127.0.0.1:6379/get/").json()
    def delete_proxy(proxy):
        requests.get("http://127.0.0.1:6379/delete/?proxy={}".format(proxy))
        

下一步编辑middleware文件

from scrapy import signals
from testproject.manager.proxypoolManager import ProxyPoolManager
from fake_useragent import UserAgent

# 创建自定义中间件
class RandomUserAgentMiddlware(object):

    def __init__(self,crawler):
        super(RandomUserAgentMiddlware,self).__init__()
        self.ua = UserAgent()  # 初始化UserAgent

    @classmethod
    def from_crawler(cls,crawler):
        return cls(crawler)

    def process_request(self, request, spider):
        request.headers.setdefault("User-Agent",self.ua.random)  # 为requests设置useragent

        retry_count = 5
        proxy = ProxyPoolManager.get_proxy().get("proxy")  # 从代理池中取出ip地址

        while retry_count > 0:
            try:
                request.meta['proxy'] = proxy
                # 使用代理访问
            except Exception:
                retry_count -= 1
                # 出错5次, 删除代理池中代理
        delete_proxy(proxy)

**因为使用了自定义中间件,所以必须要在settings.py中声名并且安排优先级

DOWNLOADER_MIDDLEWARES = {
    'testproject.middlewares.RandomUserAgentMiddlware': 333
}

跑下程序测试下
在终端输入

scrapy crawl maoyan

最后结果,成功抓取到数据了


结果.png

数据存储和导出

Scrapy提供了非常方便的导出方案,支持csv,json,xml等格式。

以本项目为例:

  • 直接导出
& scrapy crawl maoyan -o maoyan.csv

去当前目录中查看下:

image.png

小结

在这个项目中当我们了解了Scrapy框架中每个文件的作用之后,其实会感觉到爬虫项目没有想象当中那么难。遇到反爬虫也不要慌乱,先去了解反爬虫的策略后很容易就能想到针对方案。(其实一开始对反爬虫我也碰壁了~)

爬虫实战这块还没完,等有空会做一个更大一点的项目,这个练习的数据量太少了。当然对于反爬虫也会逐步深入进去。

相关文章

网友评论

    本文标题:【爬虫实战】Scrapy爬取猫眼电影

    本文链接:https://www.haomeiwen.com/subject/eclypctx.html