使用Python3+scrapy爬取某电影网站数万条数据到MySQL数据库!

一、创建scrapy爬虫

1、创建项目(CMD)

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

一、创建scrapy爬虫
1、创建项目(CMD)
注意是在CMD中使用命令,最后接创建项目的目录

scrapy startproject mvSrc D:/damo scrapy startproject mvSrc D:/damo 

2、创建爬虫文件(CMD)

  • 进入项目文件夹切换盘符:D:切换到目录:cd /damo
  • 创建爬虫文件命令:scrapy genspider xx xxx.cnxx是爬虫名称,xxx.cn是爬虫运行的网站的域名
scrapy genspider mvSpi 'yy6080.cn'
1

二、编写爬虫文件(pychar)

1、创建run文件

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

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

完成后可直接在爬虫文件(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)
123456

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)
12345678

注意:运行是运行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()
123456789101112131415161718

(2)解析二级页面

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

  • 导入库(下面步骤需要导入的库直接一并在这里导入了)
# -*- coding: utf-8 -*-
import scrapy
from ..items import MvscrItem
import re
1234
  • 编写匹配规则
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>'
123456789101112
  • 编写解析函数
    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
1234567891011121314151617

代码解释:
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)#递归
12345678

(1)编写setting.py文件,异步写入数据库

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

# mysql 配置
MYSQL_DB_NAME = 'student_db'
MYSQL_HOST = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_PASSWORD = '1234567'
12345

(2)创建数据库

- 进入数据库

mysql -uroot -p
1

- 切换

use studen_db
1

- 创建数据库

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;
12345678

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)
123456789101112131415161718192021222324252627282930313233343536373839404142

(4)再次编写items.py文件,打开管道

ITEM_PIPELINES = {
   'mvScr.pipelines.MySQLPipeline': 300,
}
123

三、运行采集

1、pychar

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

2、MySQL

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

纯手打原创,欢迎探讨。源码已打包发到个人资源,免费下载。

需要源码的加群:850591259

猜你喜欢

转载自blog.csdn.net/weixin_43881394/article/details/107711423