python爬虫框架scrapy 豆瓣实战

一曲冷凌霜 提交于 2020-08-07 09:43:24

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

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

我们发现项目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文件

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

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

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

现在就可以根据内容来编写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是爬虫的名字

运行如下图

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

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

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

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

打开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

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

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

main.py编写代码:

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

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

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

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

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

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

如图我们编写 //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打开即可

存储到数据库

接下来我们需要对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 中开启中间件并修改为我们刚刚创建的类如下图

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!