Scrapy初体验

作者: mocen_王琪 | 来源:发表于2018-09-13 11:19 被阅读5次

    学了python之后一直在给自己找点儿什么需求练练手,爬虫是学python最快的途径,就想着爬点豆瓣电影的数据吧,在经过了一系列重复造轮子之后,决定体验一下scrapy。

    scrapy的架构图:

    scrapy_architecture.png
    1、引擎(ScrapyEngine): 用来处理整个系统的通讯,数据流处理, 触发事务(框架核心)。
    2、调度器(Scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址。
    3、下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)。
    4、爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。
    5、项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
    6、下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
    7、爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
    8、调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应
    

    scrapy流程:

    1.Spider将初始url告诉Engine,Engine将url添加到调度器的请求队列中
    2.Engine从调度器队列中拿到下一个要请求的url,交给下载器(下载器中间件可以设置代理之类。。),下载器下载网页内容,交还给引擎
    3.Engine将从下载器拿到的网页内容,交给spider,spider爬取所需要的内容,生成item交还给Engine,如果需要继续爬取,将新的url告诉Engine,并添加到调度器的请求队列中
    4.pipeline 从Engine拿到爬取的实体进行处理
    

    python&scrapy安装:

    windows下安装python+scrapy

    开始

    创建项目:

    scrapy startproject 项目名称
    

    目录介绍:

    .cfg         项目配置文件  定义了项目配置文件路径,部署信息等内容
    
    items.py     定义item数据结构的地方
    
    settings.py  项目的设置文件,定义项目的全局设置 
    

    生成spiders文件:

    在spiders目录中进入命令行输入  scrapy genspider 爬虫名 要爬取的域名
    

    刷新项目文件目录

    spider文件中:
        name : 爬虫的名称
        start_urls : 为初始爬虫目录,就是第一次爬取的地址url
    

    执行爬虫文件 :

    scrapy crawl 爬虫名称
    

    爬取豆瓣电影网站内容

    在项目磁盘目录下打开命令行输入

    scrapy startproject douban_demo
    

    生成项目文件

    修改settings.py文件中USER_AGENT和ROBOTSTXT_OBEY:不然请求会被拦截

    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
    
    ROBOTSTXT_OBEY = False
    

    在spiders目录中进入命令行输入

    scrapy genspider douban_spider movie.douban.com
    

    之后会在spiders目录中生成一个douban_spider.py 的文件,修改start_urls:

    start_urls = ['http://movie.douban.com/top250']
    

    打开页面,我们接下来要抓取这些数据

    douban.png

    在items.py中创建我们的数据模型:

    class DouBanItem(scrapy.Item):
        #电影编号
        movie_num = scrapy.Field()
        #电影封面地址
        movie_imgurl = scrapy.Field()
        #电影名称
        movie_name = scrapy.Field()
        #电影参与人员
        movie_person = scrapy.Field()
        #电影评分
        movie_grade = scrapy.Field()
        #电影口号
        movie_slogen = scrapy.Field()
    

    douban_spider.py中 的 parse方法,就是我们写爬虫代码的地方

    检查页面,查看页面标签详情,可以看到页面的标签结构

    爬取数据:

    movies = response.css('div.item')
    for movie in movies:
        movie_num = movie.css('em::text').extract_first()
        movie_imgurl = movie.css('img::attr(src)').extract_first()
        movie_name = movie.css('.title::text').extract_first()
        movie_person = movie.css('.bd p::text').extract_first()
        movie_grade = movie.css('.rating_num::text').extract_first()
        movie_slogen = movie.css('.inq::text').extract_first()
    
        doubanItem = DouBanItem()
        doubanItem['movie_num'] = movie_num
        doubanItem['movie_imgurl'] = movie_imgurl
        doubanItem['movie_name'] = movie_name
        doubanItem['movie_person'] = movie_person
        doubanItem['movie_grade'] = movie_grade
        doubanItem['movie_slogen'] = movie_slogen
    

    将爬取到的数据加入pipline管道

    yield doubanItem
    

    将数据写入txt文本文件

    with open('movie_info.txt','a+',encoding='utf-8') as f:
        f.write(movie_num+" : "+movie_name+" : \t"+movie_grade+"\n")
        f.write('封面图片地址 : '+movie_imgurl+'\n')
        f.write('参与人员 : '+movie_person+'\n')
        f.write(movie_slogen+"\n")
        f.write('\n-----------------------------------------\n')
    
        使用a+追加方式,编码使用utf-8,打开文本文件,往里写入
    

    继续爬取下一页数据:

    next_page = response.css('span.next a::attr(href)').extract_first()
    if next_page is not None:
        realUrl = "http://movie.douban.com/top250"+next_page
        realUrl = response.urljoin(realUrl)
        yield scrapy.Request(realUrl,callback=self.parse)
    
    根据css找到下一页按钮中的地址,这个页面是需要拼接host地址,如果 is not None 表示还有下一页,
    urljoin(url)将地址添加到调度器请求队列中,scrapy.Request(realUrl,callback=self.parse)之情请求,设置回调使用当前parse方法作为返回数据的处理方法
    

    用爬取到的数据,生成json文件

    在命令行中(可以使用pycharm中的Terminal命令行)执行爬虫文件

    scrapy crawl douban_spider -o douban.json
    
    'douban_spider'是douban_spider.py中name字段的值
    

    执行完本地就会生成一个json文件

    用爬取到的数据,生成csv格式文件

    在命令行中(可以使用pycharm中的Terminal命令行)执行爬虫文件

    scrapy crawl douban_spider -o douban.csv
    
    'douban_spider'是douban_spider.py中name字段的值
    

    执行完本地就会生成一个csv文件

    爬取数据存储MongoDB

    首先在settings.py文件中打开 pipeline开关,并在最后面配置mongodb

    ITEM_PIPELINES = {
      'scrapy_demo.pipelines.ScrapyDemoPipeline': 300,
    }
    mongo_host = '127.0.0.1'
    mongo_port = 27017
    mongo_db_name = 'douban'
    mongo_db_collection = 'douban_movie
    

    在pipelines.py中编写代码
    首先导入settings中的mongodb配置和mongodb

    import pymongo
    from scrapy_demo.settings import mongo_db_collection,mongo_db_name,mongo_host,mongo_port
    

    在构造函数中传入配置参数:

    def __init__(self):
        # 端口号
        port = mongo_port
        # 基地址
        host = mongo_host
        # 数据库名
        dbname = mongo_db_name
        # 表名
        sheetname = mongo_db_collection
        # 创建client
        client = pymongo.MongoClient(host=host,port=port)
        # 指定数据库
        mydb = client[dbname]
        # 找到表
        self.post = mydb[sheetname]
    

    在process_item方法中进行数据插入的编写

    def process_item(self, item, spider):
        # 将模型转化为字典
        data = dict(item)
        # 将字典数据插入mongodb
        self.post.insert(data)
        return item
    

    运行之后就可以在数据库中看到咱们已经添加了数据

    0180912140030.png

    对爬虫进行伪装

    设置代理ip

    为了不让要爬取的网站发现我们的爬取动作,需要对爬虫进行一些伪装,
    我们可以通过下载器中间件(Downloader Middlewares)对我们的请求进行伪装

    将settings.py中的DOWNLOADER_MIDDLEWARES配置打开(543为优先级,数字越小,优先级越高)

    DOWNLOADER_MIDDLEWARES = {
       'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
    }
    

    在middlewares.py文件中进行编写

    创建一个中间件:

    class DoubanProcess(object):
        def process_request(self,request,spider):
            request.meta['proxy'] = '你的代理ip地址'
            # 需要登录的话-因为加密需要byte类型,所以需要在前面加b
            name_pwd = b'用户名:密码'
            # 对用户名密码加密
            encode_name_pwd = base64.b64decode(name_pwd)
            # 设置http头
            request.headers['Proxy-Authorization'] = 'Bisic ' + encode_name_pwd.decode()
    

    将你的中间件添加到settings.py的DOWNLOADER_MIDDLEWARES配置中

    DOWNLOADER_MIDDLEWARES = {
       # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
       'scrapy_demo.middlewares.DoubanProcess': 543,
    }
    

    设置随机User-Agent

    在middlewares.py文件中进行编写

    创建一个中间件:

    class DoubanUserAgent(object):
    def process_request(self,request,spider):
        # user-agent列表
        USER_AGENT_LIST = [
            'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
            'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',
            'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',
            'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',
            'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',
            'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',
            'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',
            'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
        ]
        # 使用random随机从列表中选择一个user-agent
        agent = random.choice(USER_AGENT_LIST)
        # 修改请求头
        request.headers['User_Agent'] = agent
    

    将user-agent中间件添加到 settings.py的DOWNLOADER_MIDDLEWARES配置中(优先级不能相同)

    DOWNLOADER_MIDDLEWARES = {
       # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
       'scrapy_demo.middlewares.DoubanProcess': 543,
       'scrapy_demo.middlewares.DoubanUserAgent': 544,
    }
    

    相关文章

      网友评论

        本文标题:Scrapy初体验

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