吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5201|回复: 17
收起左侧

[Python 转载] 【超简单爬虫教程剖析】使用scrapy框架爬取豆瓣TOP250电影并存入mysql

  [复制链接]
ZJL丶 发表于 2020-6-29 17:49
本帖最后由 ZJL丶 于 2020-6-29 18:02 编辑

一、 scrapy框架简介:
1. 引擎(Scrapy)
  • 用来处理整个系统的数据流处理, 触发事务(框架核心)
2. 调度器(Scheduler)
  • 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
3. 下载器(Downloader)
  • 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
4. 爬虫(Spiders)
  • 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
5. 项目管道(Pipeline)
  • 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据

二、 代码构建流程:
1)通过startproject参数创建一个scrapy项目
[Asm] 纯文本查看 复制代码
scrapy startproject item_name

2)创建spider爬虫文件(注意域的范围不要带https://等东西,只爬到一页,因为这个问题我找了好久)
[Asm] 纯文本查看 复制代码
scrapy genspider name "movie.douban.com"

3)编写主爬虫文件(/spiders/douban.py),这里边代码是负责干活的
[Asm] 纯文本查看 复制代码
import scrapy
from study.items import StudyItem

class DoubanSpider(scrapy.Spider):
        # 定义唯一标识区分爬虫,系统自动生成
    name = 'douban'
        # 定义域爬取范围
    allowed_domains = ['movie.douban.com']
        # 定义要爬取的网站
    baseurl = 'https://movie.douban.com/top250?start='
    # 定义偏移值
        offset = 0
        # 定义起始的url,系统自动生成,但是需要我们改动进行字符串拼接,方便爬取多页
    start_urls = [baseurl + str(offset)]

    def parse(self, response):
                # xpath为response中的方法,可以将xpath表达式直接作用于该函数中
                # 思路:爬取任何东西要先获取它变成一个整体(标签),然后一条一条爬取里边信息构建出一个列表
                # 例如:[movie_name,movie_link,star,quote]这是一个标签里获取的一条电影信息
                # 提醒:这个地方不要想着爬取整个网页然后在区分。
                # 例如:[name,name,name,name][link,link,link,link][star,star,star,star] ......
        moive_node = response.xpath("//div[@class='item']/div[@class='info']")
                
                # 获取moive_node里每一条电影信息(每个页面会有25个movie_node)
        for movie in moive_node:
                # 通过xpth获取每个节点的单条电影信息的内容:
                # xpath函数返回的为列表,列表中存放的数据为Selector类型的数据,所以返回给我们的是一个对象而不是我们想要的数据
        # 我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。
            # 影片名称
            movie_name = movie.xpath("./div[@class='hd']/a/span[@class='title'][1]/text()").extract()
            # 影片连接
            movie_link = movie.xpath("./div[@class='hd']/a/@href").extract()
            # 影评评分
            star = movie.xpath("./div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()").extract()
            # 影片引言
            quote = movie.xpath("./div[@class='bd']/p[@class='quote']/span[@class='inq']/text()").extract()
                        # 部分影片没有引言,所以要做判断处理
            if quote:
                quote = quote[0]
            else:
                quote = ""
                        # 将解析到的数据封装至items对象中
            item = StudyItem()
                        # 下面是提取字典中的数据(值)
                        item['movie_name'] = movie_name[0]
            item['movie_link'] = movie_link[0]
            item['star'] = star[0]
                        # 此处注意不要写[0],因为上边判断的时候已经提取了第一个元素如果在取[0]只能取到第一个数字
            item['quote'] = quote  
                        # 提交item到管道文件(pipelines.py)
            yield item
                        
                # 此处的if应该在for循环外面
                # 如果写在for循环里的话就表示每提取一条信息就执行一下if
                # 写在外边的话就是当前页面所有信息提取完了再执行下面代码
                # 通过页面url分析我们得知最后一页是225但是不能大于等于哦!
        if self.offset < 225:
                        # 通过分析得知步进值为25
            self.offset += 25
                        # 拼接url获取下一页的url
            url = self.baseurl + str(self.offset)
                        # 通过回调函数callback将下一页的url提交给parse再进行电影信息解析提取
                        # 也就是for循环25次,if的代码执行一次
                        # 注:for里面相当于每个电影,if里面相当于每一页
            yield scrapy.Request(url, callback=self.parse)
                # 注意:此方案不是最佳方案因为判断条件我写死了(因为豆瓣top250不会进行数据更新,最多250个)
                # 思路1:可以通过下一页标签用xpath提取下一页,进行url拼接,然后再传递url
                #                 需要判断什么情况下下一页是灰色,例如://a[[url=home.php?mod=space&uid=341152]@Class[/url] = next] == 0的时候
                #                 还要注意第一页的上一页也是灰色,所以判断要满足某两个条件才行
                # 思路2: 可以通过获取当前网站的总页数来进行数据爬取

4)既然爬虫文件已经获取到数据了,下一步我们就要处理spider返回的item数据(比如存储到json,mysql等等)
[Asm] 纯文本查看 复制代码
# 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


# useful for handling different item types with a single interface
# 导入我们需要的包json,mysql
from itemadapter import ItemAdapter
import pymysql
import json

class StudyPipeline(object):
    # 构造方法
    def __init__(self):
        self.f = None  # 定义一个文件描述符属性

    # 下列都是在重写父类的方法:
    # 开始爬虫时,执行一次
    def open_spider(self, spider):
        print('爬虫开始')
                # 打开一个json文件用于接收json方法写入的数据
        self.f = open('douban.json', 'w', encoding='utf-8')

    # 专门处理item对象
    # 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
    def process_item(self, item, spider):
                # 将jsondumps方法获取的数据赋值给content
                # 为什么将item转换成字典呢,因为这个item返回的值是scrapy特有的存储,python是不识别的
        content = json.dumps(dict(item), ensure_ascii=False)+",\n"
        self.f.write(content)
                # 传递到下一个被执行的管道类,一定要返回item不然就会出错
        return item
        # 关闭爬虫
    def close_spider(self, spider):
        print('爬虫结束')
        self.f.close()

# 管道文件中的一个管道类对应的是讲数据存储到一种平台
# 爬虫文件提交的item只会给管道文件中第一个被执行的管道类接受
# process_item的return item表示item传递到下一个被执行的管道类
# 将数据存储到数据库
class mysqlPipeline(object):
# pymysql插入数据简单用法
# 1. 连接connect = pymysql.connect("各种配置")
# 2. 创建游标 cursor = connect.cursor()
# 3. 执行sql语句 cursor.execute("sql")
# 4. 提交 connect.commit()
# 5. 关闭游标 cursor.close
# 6. 关闭数据库 connect.close
# 注意:56顺序不可颠倒!
    # 构造方法
    def __init__(self):
        self.conn = None  # 定义一个文件描述符属性
        self.cursor = None
        self.num = 0

    # 下列都是在重写父类的方法:
    # 开始爬虫时,执行一次
    def open_spider(self, spider):
                # 首先初始化构建一个建表sql
        sql = '''
                create table movie
                (
                movie_name varchar(500) ,
                movie_link varchar(500) ,
                star varchar(500),
                quote varchar(500)
                )
            '''
                # 连接mysql数据库
                # 注:此处的配置建议写在setting配置中
        self.conn = pymysql.connect(
            host='192.168.0.157', # IP地址
            port=3306, user='root', # 端口,账号
            password='123456', # 密码
            database='movie_top250', # 数据库名字
            charset='utf8') # 字符集
        cursor = self.conn.cursor() # 建立游标
        cursor.execute(sql) # execute方法执行sql语句
        self.conn.commit() # commit方法提交一个执行语句(只有插入和更新才需要哦)
        print('爬虫数据库开始')# print在python里需要加()

    # 专门处理item对象
    # 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
    def process_item(self, item, spider):
                # 为了方便理解,这里将item返回的数据赋值给下边插入语句使用
        movie_name = item['movie_name']
        movie_link = item['movie_link']
        star = item['star']
        quote = item['quote']
                # 执行sql前要建立一个游标,在上边方法已经连接数据库了所以这里不需要重连
        self.cursor = self.conn.cursor()
        # 进行mysql的异常捕获
                try:
                        # 插入数据时候一定要对应好行和列
                        # 下方%s格式化字符串可以用format,自行测试
            self.cursor.execute('''
                insert into movie 
                values(%s,%s,%s,%s)''', (movie_name, movie_link, star, quote))
            self.conn.commit() # 提交上方的插入sql
        except Exception as e:
            print(e)
            self.conn.rollback() # 回滚
        return item
        # 关闭游标,关闭数据库连接
    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()
        print('爬虫数据库结束')

5)最后当然就是编写配置文件了setting.py(开启管道配置文件)注意要把robots协议关掉或者注释
[Asm] 纯文本查看 复制代码
BOT_NAME = 'study'

SPIDER_MODULES = ['study.spiders']
NEWSPIDER_MODULE = 'study.spiders'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
ITEM_PIPELINES = {
   'study.pipelines.StudyPipeline': 300,
   'study.pipelines.mysqlPipeline': 320,
}


最后分享小白一个xpath工具(xpath helper)google的插件,如图:
xpath-helper.zip (131.21 KB, 下载次数: 118)

某盘: 链接:https://pan.baidu.com/s/14PUti26iAgb3zp43TZnV3w 提取码:92u6

纯手打求兄弟们点个赞!!!

ctrl+shift 用鼠标指哪里就会自动出xpath语句

ctrl+shift 用鼠标指哪里就会自动出xpath语句

免费评分

参与人数 6吾爱币 +12 热心值 +4 收起 理由
qq9199 + 1 热心回复!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
小玖 + 1 我很赞同!
fyypll + 1 + 1 谢谢@Thanks!
yudadaya + 1 + 1 热心回复!
王星星 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| ZJL丶 发表于 2020-6-29 21:53
zty521 发表于 2020-6-29 20:55
这个都需要用到的工具能否分享下呢,刚接触的小白

这个很简单,只需要安装python安装scrapy包就行了。不需要代码工具(pycharm),爬虫最难的就是网页的提取思路,并且我附带的工具你可以直接获取想要的内容的xpath路径。直接赋值到代码就可以取出来。
 楼主| ZJL丶 发表于 2021-4-15 10:41
hehehero 发表于 2020-11-13 19:29
非常不错的笔记,收藏了。顺便说下你的百度链接失效了,不知道里面是啥

是一个xpath工具,和上边一样
andyfky 发表于 2020-6-29 19:57
RoyPenn 发表于 2020-6-29 20:24
厉害兄弟,学习了
1983 发表于 2020-6-29 20:41
嗯,来看看这个爬虫怎么用
fyypll 发表于 2020-6-29 20:45
丧心病狂的注释,但是我喜欢
头像被屏蔽
zty521 发表于 2020-6-29 20:55
提示: 作者被禁止或删除 内容自动屏蔽
gaoxiaoao 发表于 2020-6-29 21:13
哥们不错,一直用网页级的requests库来爬。学习的好素材
 楼主| ZJL丶 发表于 2020-6-29 22:01
gaoxiaoao 发表于 2020-6-29 21:13
哥们不错,一直用网页级的requests库来爬。学习的好素材

一般工作中高并发多线程需要使用scrapy
 楼主| ZJL丶 发表于 2020-6-30 09:28
有问题可以直接问我,随时在
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 12:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表