python实现网络爬虫之scrapy框架

今天老师给我们讲了一下使用vscode环境下python实现爬取豆瓣电影网的信息,老师用的python是3.6.5,而我用的是3.6.4,但是结果没有什么不同。

准备工作:(1)先安装好python,我的电脑是安装的python3.6.4,安装python时第一步记得勾选添加路径 Add python3.6  to  PATH....,如果安装成功后就可以在cmd运行  python -v就可以查看到是否安装成功。

(2)接下来在进行 Python在Windows系统中的开发环境搭建,使用 pip list命令可以查看当前模块库中已经安装的所有外部模块指令。

(3)Python3.6.5在安装时默认选中的Pip模块管理组件。 setuptools 和 wheel 两个组件都是Python安装第三方模块库的依赖工具组件。 目前 Python3.6.5默认安装的pip 和 setuptools均为最新版本,但wheel模块需手动安装。 建议安装Python的外部管理模块 wheel: 安装 wheel 指令:pip install -U wheel 。安装好之后:

(4)指定国内的镜像源   :  在用户目录下的你的用户名下新建一个pip文件夹,再往pip文件夹里面添加一个pip.ini的文件(   Windows10: C:\用户\<用户名>\pip\pip.ini (pip文件夹及pip.ini 需要手动创建)   )往pip.ini文家中添加如下两行代码

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple

(5)virtualenv虚拟环境安装(多版本Python共存)

我们可以在系统中安装多个版本的Python,为了方便Python版本之间的相互切换,我们可以使用virtualenv(虚拟环境)实现同一系统中多版本共存使用的问题。

Step1:使用 pip install –U virtualenv 下载安装虚拟模块包

Step2:创建虚拟环境文件夹

今后所有的python虚拟环境都放在这个文件夹下,新建一个venvs的文件夹

使用virtualenv命令,创建跟当前系统环境相同版本的虚拟环境:

 此时可以看到新生成了一个文件夹,该文件夹就是虚拟环境:

Step3:进入当前虚拟环境 cd 虚拟文件夹名称,启动虚拟环境 虚拟环境文件夹/Script/activate

  执行:pip install -U pypiwin32 安装 

(6)Vscode安装配置,可以自行在网站下载VScode安装包进行安装

Step1:安装python开发插件,常用的如下所示:python、 Python-autopep8 、 GBKToUTF8 ;如果你的Vscode是英文的,下载中文安装包,安装第一个,安装成功后要点击重新加载才能成功,依次安装上述三个插件

Step2:将下面这个文件夹复制到我所使用的盘的根目录,我放在了F盘的根目录,进入F盘根目录下,进行离线安装,记得联网,再安装Scrapy

 Step3:在本地创建一个workspace的文件夹,由于我已经有了一个workspace文件夹,所以我创建了一个Space的文件夹,再往space文件夹里面创建一个Project_Scrapy文件夹。接下来复制此路径。cmd里面进入此路径下,再创建工程

 

(7) 测试连接

 Step1:在Vscode中导入刚刚新建的文件夹

Step2:VScode打开设置,设置python.exe的路径,操作如下

 Step3:接下来创建核心爬虫脚本程序:①使用命令:scrapy genspider 爬虫脚本名称 访问网站的域名

 Step4:我们是通过程序从网站上爬取数据,但是并不是所有的网站都允许程序的访问,所以要测试一下程序与网站的连接情况。测试的方法,仅需一条指令:scrapy shell 网站Url地址。

测试常见的结果:200 正常       403 拒绝访问(浏览器访问没问题,拒绝程序的访问)

 在项目下添加一个rotate_useragent.py文件,文件内容如下 

# -*- coding: utf-8 -*-
'''
    rotate_useragent.py
    --------------------------------
    用户代理轮循检索器

    @Copyright: Chinasoft Interntional·ETC
    @Author: Alvin
    @Date: 2018-01-16
'''

# 导入random模块
import random
# 导入useragent用户代理模块中的UserAgentMiddleware类
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware

# RotateUserAgentMiddleware类,继承 UserAgentMiddleware 父类
# 作用:创建动态代理列表,随机选取列表中的用户代理头部信息,伪装请求。
#       绑定爬虫程序的每一次请求,一并发送到访问网址。

# 发爬虫技术:由于很多网站设置反爬虫技术,禁止爬虫程序直接访问网页,
#             因此需要创建动态代理,将爬虫程序模拟伪装成浏览器进行网页访问。
class RotateUserAgentMiddleware(UserAgentMiddleware):
    def __init__(self, user_agent=''):
        self.user_agent = user_agent

    def process_request(self, request, spider):
        #这句话用于随机轮换user-agent
        ua = random.choice(self.user_agent_list)
        if ua:
            # 输出自动轮换的user-agent
            print(ua)
            request.headers.setdefault('User-Agent', ua)

    # the default user_agent_list composes chrome,I E,firefox,Mozilla,opera,netscape
    # for more user agent strings,you can find it in http://www.useragentstring.com/pages/useragentstring.php
    # 编写头部请求代理列表
    user_agent_list = [\
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"\
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",\
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",\
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",\
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",\
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",\
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",\
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",\
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",\
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",\
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",\
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
       ]

可以发现项目中也自动显示了这一文件

 现在轮询文件已经考进去了,但是scrapy框架还不知道,所以要让scrapy框架知道,方法是配置settings.py文件。打开settings.py,找到

#DOWNLOADER_MIDDLEWARES = {
#    'doubanmovie.middlewares.DoubanmovieDownloaderMiddleware': 543,
#}

 将注释去掉并添加以下代码

DOWNLOADER_MIDDLEWARES = {
   'doubanmovie.middlewares.DoubanmovieDownloaderMiddleware': 543,
   'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware' : None,
    'doubanmovie.rotate_useragent.RotateUserAgentMiddleware' :400
}

之后保存即可生效 ,回到cmd命令下,再一次运行刚才的语句,即可成功

 (8)正式爬取网站数据

Step1:明确爬取哪部分信息,此处我们主要爬取豆瓣的电影的排行榜的排名以及标题title,查看页面的源代码,分析要爬取数据的页面结构,可以发现每一个小块均存在   li 标签   下

 Step2:打开工程中的item.py文件,设置要采集的数据项:Scrapy框架中的 items.py 文件以采集对象的方式存在,将每一个采集项作为一个采集对象的属性处理。而且,每一个属性统一使用  scrapy.Field( ) 函数创建,非常方便

class DoubanmovieItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 排名
    rank = scrapy.Field()
    #名称
    title = scrapy.Field()
    pass

Step3:重点+难点:编写 moviespider.py 解析HTML标签获取数据

 增加代码

# -*- coding: utf-8 -*-
import scrapy
# 导入items.py中的DoubanmovieItem类
from doubanmovie.items import DoubanmovieItem

class MoviespiderSpider(scrapy.Spider):
    name = 'moviespider'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # 获取当前页面中所有的class为item的标签
        movie_items = response.xpath('//div[@class="item"]')
        # 遍历
        for item in movie_items:
            # 创建DoubanmovieItem对象
            movie = DoubanmovieItem()
            # XPath解析获取电影排名赋值给movie对象的rank属性
            movie['rank'] = item.xpath('div[@class="pic"]/em/text()').extract()
            # XPath解析获取电影排=名赋值给movie对象的title属性
            movie['title'] = item.xpath('div[@class="info"]/div[@class="hd"]/a/span[@class="title"]/text()').extract()
            # 将movie添加到一个生成器(列表)中
            yield movie
            pass
        # 自动请求翻页实现爬虫的深度采集
        nextPage = response.xpath('//span[@class="next"]/a/@href')
        # 判断nextPage是否有效(是否到达最后一页)
        if nextPage:
            # 拼接下一页的地址
            url = response.urljoin(nextPage[0].extract())
            # 发送url后页请求
            yield scrapy.Request(url, self.parse)
        pass

 Step4:编写 piplines.py 设置控制台输出,打开piplines.py文件,添加如下代码:

class DoubanmoviePipeline(object):
    def process_item(self, item, spider):
        print('电影排名:{0}' .format(item['rank'][0]))
        print('电影名字:{0}' .format(item['title'][0]))
        return item

 要想启用该 输出模式,需要在 settings.py 文件中设置 输出项即可

然后在cmd里面运行 

(6)对数据进行存储

 Step1:采用json存储

通过前面的讲解我们知道,控制输出的文件是piplines.py ,那么我们创建一个新的piplines2json.py 文件,来控制文件输出到json。   ①在同级目录下复制piplines.py文件,重命名为piplines2json.py。②打开文件,将输出到控制台的代码删除掉,留下基本模板。  ③接下来在构造方法中,判断是否有将要保存文件的文件夹,如果没有,则创建。这里要创建文件夹需要导入os模块   ④这里为什么要把创建文件夹的代码写在构造方法而不是process_item方法中呢,因为如果写在process_item方法中,那么每输出一条数据就会创建一个文件夹,这显然不是我们想要的结果。在process_item方法中添加写入json文件的代码:

import os
import time
import json

class DoubanmoviePipeline(object):

    # 创建一个构造方法,用于创建所有类型输出文件的文件夹
    def __init__(self):
        # 设置输出文件夹的名称
        self.folderName = 'output'
        # 判断文件夹是否存在
        if not os.path.exists(self.folderName):
            # 创建文件夹
            os.mkdir(self.folderName)

    def process_item(self, item, spider):
        # 输出提示
        print('>> write to json file......')
        # 获取当前日期的字符串类型数据
        now = time.strftime('%Y%m%d', time.localtime())
        # 设置json文件名称
        jsonFileName = 'doubanmovie_' + now + '.json'
        try:
            # 打开json文件,以追加的方式
            with open(self.folderName + os.sep + jsonFileName, 'a', encoding="utf-8") as jsonfile:
                # 当前数据序列化为json格式
                data = json.dumps(dict(item), ensure_ascii=False) + '\n'
                # 写入到json文件
                jsonfile.write(data)
        except IOError as err:
            # 输出错误信息
            raise('json file error: {0}' .format(str(err)))
        finally:
            #关闭文件流
            jsonfile.close()

        return item

 Settings.py中也需要添加代码:

同样cmd下运行

 Step2:采用Excel存储

首先安装Excel所需的三个插件

新增pipelines2excel.py文件: 代码如下

import time
import xlwt
import xlrd
from xlutils.copy import copy

class DoubanmoviePipeline(object):

    # 构造方法:创建一个excel文件以及内容模板
    def __init__(self):
       folder_name = 'output'
       current_date = time.strftime('%Y%m%d', time.localtime())
       file_name = 'doubanmovie_' + current_date + '.xls'
       # 最终的文件路径
       self.excelPath = folder_name + '/' + file_name

       # 构建workbook工作簿
       self.workbook = xlwt.Workbook(encoding='UTF-8')
       # 创建sheet工作页
       self.sheet = self.workbook.add_sheet(u'豆瓣电影数据')
       # 设置excel内容的标题
       headers = ['排名', '电影名']
       # 设置标题文字的样式
       headStyle = xlwt.easyxf('font: color-index black, bold on')
       # for循环写入标题内容
       for colIndex in range(0, len(headers)):
           # 按照规定好的字体样式将标题内容写入
           self.sheet.write(0, colIndex, headers[colIndex], headStyle)
           pass

       # 保存创建好的excel文件
       self.workbook.save(self.excelPath)
       # 全局变量行数
       self.rowIndex = 1
       pass

    def process_item(self, item, spider):
        
        # 提示信息
        print('>>>>>> write to Excel .................')
        # 读取已经创建好的excel文件
        oldWb = xlrd.open_workbook(self.excelPath, formatting_info=True)
        # 拷贝一个副本
        newWb = copy(oldWb)
        # 获取到excel要操作的sheet工作页
        sheet = newWb.get_sheet(0)
        # 将采集到的数据转换成一个List列表
        line = [item['rank'], item['title']]
        # 使用for循环遍历excel中的每一个cell格(行,列)
        for colIndex in range(0, len(item)):
            #将数据写入到指定的行列中去
            sheet.write(self.rowIndex, colIndex, line[colIndex])
            pass
        
        # 完毕后保存excel文件,自动覆盖原有的文件
        newWb.save(self.excelPath)
        # 全局行变量+1
        self.rowIndex = self.rowIndex + 1
        return item

Settings.py文件中配置:

再次运行 

输出已有xls文件 

 Step3:上传mysql数据库

新建crawl数据库,新建movieinfo表,添加以下属性

 安装pymysql使得python可以连接数据库

新建pipelines2mysql.py文件: 文件代码

# 导入mysql模块
import pymysql

class DoubanmoviePipeline(object):
    def process_item(self, item, spider):

        # 设置一个全局的连接对象
        connection = ''
        try:
        
            # 获取一个有效的数据库连接对象
            connection = pymysql.connect(host='localhost', port=3306,\
                                        user='root', password='970301cx',\
                                        db='crawl', charset='utf8')
            if connection:
                print('>>> MySql >>>  正确获取数据库连接对象')
            
            # 创建一个游标对象
            cursor = connection.cursor()
            print('>>> MySql >>>  正确获取游标对象')

            # 设置插入数据的SQL语句模板
            rank = int(item['rank'][0])#将排名强制转换为整形
            title = item['title'][0]
            sql = 'insert into movieinfo values(null, %d, \'%s\')' %(rank, title)
            print('>>> MySql >>>  %s' %sql)

            # 使用游标对象发送SQL语句并将服务器结果返回
            affectedRows = cursor.execute(sql)
            msg = '>>> MySql >>>  写入操作成功' if affectedRows > 0 else '>>> MySql >>>  写入操作失败'
            print(msg)

            # 事务提交
            connection.commit()
            print('>>> MySql >>>  事务提交')

        except:

            # 事务回滚
            connection.rollback()
            print('>>> MySql >>>  事务回滚')

        finally:

            # 关闭数据库连接
            connection.close()
            print('>>> MySql >>>  关闭数据库连接')

        return item

修改setting.py

运行结果 

查看一下 mysql数据库中的内容

至此,今天的学习内容已经结束了 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值