python爬虫框架scrapy 豆瓣实战

系统 1455 0

Scrapy

官方介绍是

An open source and collaborative framework for extracting the data you need from websites.

In a fast, simple, yet extensible way.

意思就是

一个开源和协作框架,用于以快速,简单,可扩展的方式从网站中提取所需的数据。


 

环境准备

本文项目使用环境及工具如下

  • python3
  • scrapy
  • mongodb

python3 scrapy的安装就不再叙述

mongodb是用来存储数据的nosql非关系型数据库 官方下载地址https://www.mongodb.com/download-center/community?jmp=docs

mongodb图形化管理工具推荐使用nosqlmanager


 项目创建

没错,我们还是挑软柿子捏,就爬取最简单的豆瓣电影top250

这个网站几乎是每个学习爬虫的人都会去爬取的网站,这个网站特别有代表性 话不多说,项目开始

创建scrapy项目需要在命令行中进行

切换到工作目录,然后输入指令  scrapy startproject douban

python爬虫框架scrapy 豆瓣实战_第1张图片

即创建成功,然后使用pycharm打开项目 首先看下目录结构

python爬虫框架scrapy 豆瓣实战_第2张图片

我们发现项目spiders中只有一个文件,放爬虫的地方怎么会只有一个__init__.py呢 

别急我们还需要输入一个命令来创建基本爬虫  打开cmd切换到目录文件夹下的spiders目录

输入 scrapy genspider douban_spider https://movie.douban.com/top250

如下图创建爬虫成功  

然后我们打开项目分析目录结构

douban                                                      项目文件夹

  spiders                爬虫文件夹

    __init__.py

    douban_spider.py       爬虫文件

  __init__.py

  ietms.py              定义items数据结构的地方(即我们爬取内容的属性之类的信息)

  middlewares.py          中间件

  pipelines.py           定义对于items的处理方法(数据清洗等)(需要在settings中开启pipelines选项)

  settings.py            项目的设置文件,定义全局的各种设置(比如头部代理,任务并发量,下载延迟等等)

scrapy.cfg                                                 项目的配置文件(包含一些默认的配置信息)

至此我们的的项目算是创建成功了


 

确定内容

创建好项目之后下一步就是确定我们要爬取的内容了,然后才可以开始编写我们的items.py文件

首先打开目标网页进行分析 

python爬虫框架scrapy 豆瓣实战_第3张图片

网页中有哪些东西是我们需要的呢?

  • 电影排名编号
  • 电影名称
  • 电影演职员以及年份分类
  • 电影星级评分 
  • 评论人数
  • 电影简介 

现在就可以根据内容来编写items.py文件了

items.py文件代码编写如下

            
              #
            
            
               -*- coding: utf-8 -*-
            
            
              #
            
            
               Define here the models for your scraped items
            
            
              
#
#
            
            
               See documentation in:
            
            
              
#
            
            
               https://docs.scrapy.org/en/latest/topics/items.html
            
            
              import
            
            
               scrapy



            
            
              class
            
            
               DoubanItem(scrapy.Item):
    
            
            
              #
            
            
              示例
            
            
              #
            
            
               define the fields for your item here like:
            
            
              #
            
            
               name = scrapy.Field()
            
            
              
    serial_number 
            
            = scrapy.Field()
            
              #
            
            
              排名
            
            
    movie_name = scrapy.Field()
            
              #
            
            
              电影名称
            
            
    introduce = scrapy.Field()
            
              #
            
            
              电影简介基本信息
            
            
    star = scrapy.Field()
            
              #
            
            
              电影星级评分
            
            
    evaluate = scrapy.Field()
            
              #
            
            
              电影评论人数
            
            
    describe = scrapy.Field()
            
              #
            
            
              电影内容简介
            
          

 


 

内容提取spider文件编写

确定内容之后就是非常关键的spider爬虫文件编写了 

测试阶段douban_spider.py文件编写如下:

            
              #
            
            
               -*- coding: utf-8 -*-
            
            
              import
            
            
               scrapy



            
            
              class
            
            
               DoubanSpiderSpider(scrapy.Spider):
    
            
            
              #
            
            
              爬虫名字
            
            
    name = 
            
              '
            
            
              douban_spider
            
            
              '
            
            
              #
            
            
              允许的域名 爬取url都属于这个域名
            
            
    allowed_domains = [
            
              '
            
            
              movie.douban.com
            
            
              '
            
            
              ]
    
            
            
              #
            
            
              起始url
            
            
    start_urls = [
            
              '
            
            
              https://movie.douban.com/top250/
            
            
              '
            
            
              ]

    
            
            
              def
            
            
               parse(self, response):
        
            
            
              print
            
            (response.text)
            
              #
            
            
              打印响应内容
            
            
              pass
            
          

然后我们需要运行下我们的爬虫看下现在能否出什么信息

打开命令窗口并cd到项目目录下输入命令   scrapy crawl douban_spider

douban_spider是爬虫的名字

运行如下图

python爬虫框架scrapy 豆瓣实战_第4张图片

发现里面有爬虫的信息也有返回响应的信息,但是我们可以看出来没有我们想要的电影信息,现在怎么办?

稍微学习过爬虫的同学都知道,爬虫是需要修改 USER_AGENT 的,这也是最简单的反爬虫机制,所以我们同样需要去修改我们爬虫的用户代理

去哪找头部代理呢?简单一点的可以直接去百度搜索一个,或者呢我们用浏览器调试台把自己的用户代理复制下来

例如chrome浏览器按F12点击一个资源复制出来用户代理即可不再赘述

python爬虫框架scrapy 豆瓣实战_第5张图片

打开settings.py文件  找到USER_AGENT修改如下:

            
              #
            
            
               Crawl responsibly by identifying yourself (and your website) on the user-agent
            
            
              
#
            
            
              USER_AGENT = 'douban (+http://www.yourdomain.com)'
            
            
USER_AGENT = 
            
              '
            
            
              Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36
            
            
              '
            
          

然后我们再次打开命令窗口并cd到项目目录下输入命令   scrapy crawl douban_spider

python爬虫框架scrapy 豆瓣实战_第6张图片

发现已经有了我们想要的电影信息

同时每次在命令行运行spider确实不方便,我们可以在项目中添加一个main.py的启动文件如下

python爬虫框架scrapy 豆瓣实战_第7张图片

main.py编写代码:

            
              from
            
             scrapy 
            
              import
            
            
               cmdline
cmdline.execute(
            
            
              '
            
            
              scrapy crawl douban_spider
            
            
              '
            
            .split())
          

运行,发现就得到了与命令行运行一样的效果了

接下来的工作就是 数据处理 了,提取出我们想要的信息  继续编写spider.py文件

对于数据的提取我们使用xpath定位 先来观察目标网站的元素 我们可以看到top250电影中每一页有25个电影信息 并且每个电影信息都是一个列表 li

python爬虫框架scrapy 豆瓣实战_第8张图片

xpath有好多种写法 我们可以审查元素然后编写xpath定位,或者呢直接用chrome也可以直接获取某元素的xpath路径

例如使用某xpath浏览器插件来找我们需要的元素 我们首先先找到每个电影的定位

python爬虫框架scrapy 豆瓣实战_第9张图片

如图我们编写 //ol[@class='grid_view']/li/div[@class='item'] 就可以定位到当前每个电影 其实我们简单点直接写 //ol/li 也可以,但是我们最好直接精确一点 xpath语法如下

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

然后同理,我们就可以找到电影排名,名称,评论等等信息的xpath, 接下来在spider.py文件中引用我们的 items.py中编写的DoubanItem类 然后完成对象属性的赋值

spider.py文件代码:

            
              #
            
            
               -*- coding: utf-8 -*-
            
            
              import
            
            
               scrapy

            
            
              from
            
             douban.items 
            
              import
            
            
               DoubanItem



            
            
              class
            
            
               DoubanSpiderSpider(scrapy.Spider):
    
            
            
              #
            
            
              爬虫名字
            
            
    name = 
            
              '
            
            
              douban_spider
            
            
              '
            
            
              #
            
            
              允许的域名 爬取url都属于这个域名
            
            
    allowed_domains = [
            
              '
            
            
              movie.douban.com
            
            
              '
            
            
              ]
    
            
            
              #
            
            
              起始url
            
            
    start_urls = [
            
              '
            
            
              https://movie.douban.com/top250/
            
            
              '
            
            
              ]

    
            
            
              #
            
            
              默认解析方法
            
            
              def
            
            
               parse(self, response):
        
            
            
              #
            
            
               注意在python语句中使用xpath如 注意与原来语句单双引号的问题
            
            
        movie_list=response.xpath(
            
              "
            
            
              //ol[@class='grid_view']/li/div[@class='item']
            
            
              "
            
            
              )
        
            
            
              for
            
             movie_item 
            
              in
            
            
               movie_list:
            douban_item
            
            =
            
              DoubanItem()
            
            
            
              #
            
            
              xpath语句最后的text()是获取当前xpath的内容
            
            
              #
            
            
               scrapy get() getall()方法获得xpath路径的值 两种方法不同请百度
            
            
            douban_item[
            
              '
            
            
              serial_number
            
            
              '
            
            ] = movie_item.xpath(
            
              "
            
            
              .//em/text()
            
            
              "
            
            
              ).get()
            douban_item[
            
            
              '
            
            
              movie_name
            
            
              '
            
            ] = movie_item.xpath(
            
              "
            
            
              .//span[@class='title']/text()
            
            
              "
            
            
              ).get()
            
            
            
              #
            
            
              介绍的内容非常不规范并且有好多行,首先使用getall()来获取,然后我们要对其进行处理
            
            
            content = movie_item.xpath(
            
              "
            
            
              .//div[@class='bd']/p[1]/text()
            
            
              "
            
            
              ).getall()
            
            
            
              #
            
            
              处理
            
            
            contient_introduce=
            
              ''
            
            
              for
            
             conitem 
            
              in
            
            
               content:
                content_s
            
            =
            
              ''
            
            
              .join(conitem.split())
                contient_introduce
            
            =contient_introduce+content_s+
            
              '
            
            
              '
            
            
              #
            
            
              赋值
            
            
            douban_item[
            
              '
            
            
              introduce
            
            
              '
            
            ] =
            
               contient_introduce
            douban_item[
            
            
              '
            
            
              star
            
            
              '
            
            ] = movie_item.xpath(
            
              "
            
            
              .//span[@class='rating_num']/text()
            
            
              "
            
            
              ).get()
            douban_item[
            
            
              '
            
            
              evaluate
            
            
              '
            
            ] = movie_item.xpath(
            
              "
            
            
              .//div[@class='star']/span[4]/text()
            
            
              "
            
            
              ).get()
            douban_item[
            
            
              '
            
            
              describe
            
            
              '
            
            ] = movie_item.xpath(
            
              "
            
            
              .//div[@class='bd']/p[2]/span/text()
            
            
              "
            
            
              ).get()
            
            
            
              #
            
            
              我们需要把获取到的东西yield到douban_item中,否则我们的管道pipelines.py无法接收数据
            
            
              yield
            
            
               douban_item

        
            
            
              #
            
            
              我们需要自动翻页到下一页去解析数据
            
            
        next_linkend=response.xpath(
            
              "
            
            
              //span[@class='next']/a/@href
            
            
              "
            
            
              ).get()
        
            
            
              #
            
            
              判断next_linkend是否存在
            
            
              if
            
            
               next_linkend:
            next_link 
            
            = 
            
              '
            
            
              https://movie.douban.com/top250/
            
            
              '
            
            +
            
              next_linkend
            
            
            
              #
            
            
              同样需要yield提交到调度器中 同时添加一个回调函数(刚刚编写的数据提取函数)
            
            
              yield
            
             scrapy.Request(next_link,callback=self.parse)
          

数据存储

我们可以使用命令直接将数据保存到 json或者csv文件如下

还是使用命令行   cd到项目目录  

输入命令  scrapy crawl douban_spider -o test.json 就可以得到一个json文件

输入命令  scrapy crawl douban_spider -o test.csv  就可以得到一个csv文件

这个csv文件可以直接用excel打开浏览,但是我们会发现存在乱码,我们可以先用notepad++打开文件改下编码方式然后保存再用excel打开即可

python爬虫框架scrapy 豆瓣实战_第10张图片

存储到数据库

接下来我们需要对pipelines.py进行编写,将数据存储到mongodb中

注意 我们需要在setting.py中将 ITEM_PIPELINES 的注释关掉,这样才能正常的运行pipelines.py

pipelines.py代码:

            
              #
            
            
               -*- coding: utf-8 -*-
            
            
              #
            
            
               Define your item pipelines here
            
            
              
#
#
            
            
               Don't forget to add your pipeline to the ITEM_PIPELINES setting
            
            
              
#
            
            
               See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
            
            
              import
            
            
               pymongo

            
            
              #
            
            
              连接本地数据库   远程也可以
            
            
myclient = pymongo.MongoClient(
            
              "
            
            
              mongodb://localhost:27017/
            
            
              "
            
            
              )

            
            
              #
            
            
              数据库名称
            
            
mydb = myclient[
            
              "
            
            
              douban
            
            
              "
            
            
              ]

            
            
              #
            
            
              数据表名称
            
            
mysheet = mydb[
            
              "
            
            
              movie
            
            
              "
            
            
              ]


            
            
              class
            
            
               DoubanPipeline(object):
    
            
            
              #
            
            
              此中的item就是刚刚yield回来的
            
            
              def
            
            
               process_item(self, item, spider):
        data
            
            =
            
              dict(item)
        
            
            
              #
            
            
              插入数据
            
            
                      mysheet.insert(data)
        
            
            
              return
            
             item
          

现在运行 main.py 数据就存储到数据库之中了,我们可以打开数据库查看数据

至此,我们的爬虫项目可以说已经完成了。


 

爬虫伪装

  • ip代理中间件
  • user-agent中间件

ip代理需要购买服务器然后可以使用先不提了 

我们尝试下user-agent中间件

编写middlewares.py再最后新加入我们自己编写的类(文件最上端要 import random):

            
              class
            
            
               my_useragent(object):
    
            
            
              def
            
            
               process_request(self,request,spider):
        USER_AGENT_LIST 
            
            =
            
               [
            
            
            
              "
            
            
              Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20
            
            
              "
            
            
              ,
            
            
            
              "
            
            
              Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52
            
            
              "
            
            
              ,
        ]
        agent 
            
            =
            
               random.choice(USER_AGENT_LIST)
        request.headers[
            
            
              '
            
            
              User_Agent
            
            
              '
            
            ] = agent
          

然后去 settings.py 中开启中间件并修改为我们刚刚创建的类如下图

python爬虫框架scrapy 豆瓣实战_第11张图片

然后再运行 main.py 就都OK了。

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论