您的位置:首页 > 编程语言 > Python开发

[Python爬虫实例项目]深度解析!使用Python3+scrapy+pymysql爬取某电影网站数万条数据到MySQL数据库

2020-07-05 23:23 369 查看

文章目录

  • 二、编写爬虫文件(pychar)
  • 3、编写获取二级详情页面
  • 4、解析下一页,并存储
  • 三、运行采集
  • 一、创建scrapy爬虫

    1、创建项目(CMD)

    注意是在CMD中使用命令,最后接创建项目的目录

    scrapy startproject mvSrc D:/damo

    2、创建爬虫文件(CMD)

    • 进入项目文件夹
      切换盘符:D:
      切换到目录:cd /damo

    • 创建爬虫文件

      命令:scrapy genspider xx xxx.cn

      xx是爬虫名称,xxx.cn是爬虫运行的网站的域名

    scrapy genspider mvSpi 'yy6080.cn'

    二、编写爬虫文件(pychar)

    1、创建run文件

    在pychar中创建run.py文件(可命名为其他),方便直接在pychar里面运行,无需到CMD当中运行

    from scrapy import cmdline
    #mvSpi后接 --nolog,为无日志模式输出
    cmdline.execute('scrapy crawl mvSpi'.split())

    完成后可直接在爬虫文件(mvSpi.py)中输出response.text,查看是否跑的通

    class MvspiSpider(scrapy.Spider):
    name = 'mvSpi'
    allowed_domains = ['yy6080.cn']
    start_urls = ['http://www.yy6080.cn/vodtypehtml/1.html']
    def parse(self, response):
    print(response.text)

    2、分析网页,编写爬虫文件

    (1)查看网页,确定采集内容的结构
    • 查看首页
    • 查看二级页面

      网页结构简单,不做赘述

    3、编写获取二级详情页面

    def parse(self, response):
    print(response.text)
    analUrl = response.xpath('//div/a/img/../@href').extract()
    for url in analUrl:
    yield scrapy.Request('http://www.yy6080.cn'+url,callback=self.analyHtml)
    
    def analyHtml(self,response):
    print(response.text)

    注意:运行是运行run.py文件,并非mvSpi.py文件!

    (1)编写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 MvscrItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()
    update = scrapy.Field()
    actor = scrapy.Field()
    score = scrapy.Field()
    mvUrl = scrapy.Field()
    (2)解析二级页面

    我使用的是正则表达式,可使用xpath或其他

    • 导入库(下面步骤需要导入的库直接一并在这里导入了)
    # -*- coding: utf-8 -*-
    import scrapy
    from ..items import MvscrItem
    import re
    • 编写匹配规则
    class MvspiSpider(scrapy.Spider):
    name = 'mvSpi'
    allowed_domains = ['yy6080.cn']
    start_urls = ['http://www.yy6080.cn/vodtypehtml/1.html']
    
    reUrl = 'position:relative;display:block;.*?href="(.*?)"'
    reName = 'movie-title">(.*?)<'
    reUpdateTime = '更新时间:(.*?)<'
    reActor = '导演.*?\n.*?>.*?>(.*?)<'
    reScore = '评分.*?\n.*?>(.*?)<'
    reMvUrl = 'panel panel-default resource-list ptab ptabw.*?\n.*?\n.*?\n.*?\n.*?href="(.*?)"'
    reNext = '<a target="_self" href=">(.*?).*?>下一页</a>'
    • 编写解析函数
    def __init__(self):
    self.item = MvscrItem()
    
    def analyHtml(self,response):
    # print(response.text)
    html = response.text
    tmpName = re.findall(self.reName,html,re.S) if re.findall(self.reName,html,re.S) else '-'
    self.item['name'] = ''.join(tmpName)
    tmpUpdate = re.findall(self.reUpdateTime, html, re.S) if re.findall(self.reUpdateTime, html, re.S) else '-'
    self.item['update'] = ''.join(tmpUpdate)
    tmpActor = re.findall(self.reActor, html, re.S) if re.findall(self.reActor, html, re.S) else '-'
    self.item['actor'] = ''.join(tmpActor)
    tmpScore = re.findall(self.reScore, html, re.S) if re.findall(self.reScore, html, re.S) else '-'
    self.item['score'] = ''.join(tmpScore)
    tmp = re.findall(self.reMvUrl, html, re.S) if re.findall(self.reMvUrl, html, re.S)  else '-'
    self.item['mvUrl'] = ''.join(tmp)
    yield self.item

    代码解释:
    tmpName = re.findall(self.reName,html,re.S) if re.findall(self.reName,html,re.S) else ‘-’

    :if...esle...三目运算,防止解析的数据为空,写入数据库导致报错

    self.item[‘name’] = ‘’.join(tmpName)
    :''.join...拼接,有些解析出来有两个结果,比如有两个播放URL,同样是为了防止写入数据库报错

    由于对接的数据库是关系型数据库,所以在爬虫解析方法上做了一些特殊处理,防止写入的数据是空数据或者列表型数据(MySQL不支持写入列表但是Mongo可以,当时给我整蒙了),如果是直接写入CSV或者非关系型数据库,analyHtml可以精简许多。

    4、解析下一页,并存储

    到了第(4)步,基本上就完成了大部分的解析内容,但只是首页的内容,如果需要采集所有页面的内容,还需要解析下一页的规则


    简单分析发现仅仅是URL变化,直接做一个拼接即可

    def parse(self, response):
    #print(response.text)
    analUrl = response.xpath('//div/a/img/../@href').extract()
    for url in analUrl:
    yield scrapy.Request('http://www.yy6080.cn'+url,callback=self.analyHtml)
    for i in range(2,1044):#下一页
    tmpUrl = f'http://www.yy6080.cn/vodtypehtml/1-{i}.html'
    yield scrapy.Request(tmpUrl,callback=self.parse)#递归
    (1)编写setting.py文件,异步写入数据库

    由于采集的数据较多,防止拥塞影响爬虫效率,故使用异步

    # mysql 配置
    MYSQL_DB_NAME = 'student_db'
    MYSQL_HOST = '127.0.0.1'
    MYSQL_USER = 'root'
    MYSQL_PASSWORD = '1234567'
    (2)创建数据库

    - 进入数据库

    mysql -uroot -p

    - 切换

    use studen_db

    - 创建数据库

    CREATE TABLE mvtable(
    mv_name varchar(100),
    mv_update VARCHAR(200) ,
    mv_actor varchar(200) NOT NULL,
    mv_score varchar(50),
    mv_mvUrl varchar(200),
    PRIMARY KEY ( mv_mvUrl )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    varchar写大点,防止出现写入失败的情况

    (3)编写piplines.py文件
    # -*- coding: utf-8 -*-
    import pymysql
    # 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
    
    class MySQLPipeline(object):
    
    # 打开数据库
    def open_spider(self, spider):
    db = spider.settings.get('MYSQL_DB_NAME','student_db')
    host = spider.settings.get('MYSQL_HOST', 'localhost')
    port = spider.settings.get('MYSQL_PORT', 3306)
    user = spider.settings.get('MYSQL_USER', 'root')
    passwd = spider.settings.get('MYSQL_PASSWORD', '1234567')
    
    self.db_conn =pymysql.connect(host=host, port=port, db=db, user=user, passwd=passwd, charset='utf8')
    self.db_cur = self.db_conn.cursor()
    
    # 关闭数据库
    def close_spider(self, spider):
    self.db_conn.commit()
    self.db_conn.close()
    
    # 对数据进行处理
    def process_item(self, item, spider):
    self.insert_db(item)
    return item
    
    #插入数据
    def insert_db(self, item):
    values = (
    item['name'],
    item['update'],
    item['actor'],
    item['score'],
    item['mvUrl'],
    )
    
    sql = 'INSERT INTO mvtable VALUES(%s,%s,%s,%s,%s)'
    self.db_cur.execute(sql, values)
    (4)再次编写items.py文件,打开管道
    ITEM_PIPELINES = {
    'mvScr.pipelines.MySQLPipeline': 300,
    }

    三、运行采集

    1、pychar

    红色的是日志,如果在run.py中接--nolog,则直接输出结果。

    2、MySQL

    MySQL运行结果,只爬取了500+(我也不知道为什么乱码)


    纯手打原创,欢迎探讨。源码已打包发到个人资源,免费下载。
    参考链接:scrapy写入各类型数据库配置方法

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐