小工具知识网

当前位置: 首页 > 行业知识 > Scrapy框架(高效爬虫)

行业知识

Scrapy框架(高效爬虫)

2026-11-10 01:38:26 来源:互联网转载

文章目录

  • 一、环境配置
  • 二、创建项目
  • 三、scrapy数据解析
  • 四、基于终端指令的持久化存储
    • 1、基于终端指令
    • 2、基于管道
    • 3、数据同时保存至本地及数据库
    • 4、基于spider爬取某网站各页面数据
    • 5、爬取本页和详情页信息(请求传参)
    • 6、图片数据爬取ImagesPipeline
    • 五、中间件
      • 1、拦截请求中间件(UA伪装,代理IP)
      • 2、拦截响应中间件(动态加载)
      • 六、CrawlSpider(自动请求全站爬取,全部页面,自动下拉滚轮爬取)
      • 七、分布式爬虫
      • 八、增���式爬虫

        Scrapy拥有高性能持久化存储,异步数据下载,高性能数据解析,分布式功能

        一、环境配置

        环境配置步骤如下(要按步骤来):

        pip install wheel下载twisted:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted安装twisted:pip install Twisted-17.1.0-cp36m-win_amd64.whl   (这个文件的路劲)pip install pywin32pip install scrapy测试:在终端输入scrapy指令,没有报错表示安装成功

        二、创建项目

        步骤:

        1、打开pycharm的terminal2、scrapy startproject first3、cd first4、scrapy genspider main www.xxx.com5、需要有main.py里面的输出,则修改settings.py里面的ROBOTSTXT_OBEY = True改为False6、scrapy crawl main  不需要额外的输出则执行scrapy crawl main --nolog   或者在settings.py里面添加LOG_LEVEL='ERROR',main.py有错误代码会报错(不添加有错误时则不会报错)(常用)

        实际操作如下:

        打开pycharm的terminal

        执行scrapy startproject first,当前目录下会出现个first项目工程,里面有个spiders文件夹,称为爬虫文件夹,在这里放爬虫源文件

        cd first 进入工程目录

        执行scrapy genspider main www.xxx.com,在spiders目录中创建一个名为main的爬虫文件,创建的文件自带部分内容

        执行工程:scrapy crawl main (运行main爬虫文件)

        上面parse里面如果有输出运行时没有输出,则需要将settings.py里面的ROBOTSTXT_OBEY = True改为False

        改成False后,修改main.py文件内容如下,运行就会有输出

        import scrapyclass MainSpider(scrapy.Spider):    # 爬虫文件的名称:爬虫源文件的唯一标识    name = "main"    # 允许的域名:用来限定start_urls列表中哪些url可以进行请求发送,一般不用    # allowed_domains = ["www.xxx.com"]    # 起始的url列表:该列表中存放的url会被scrapy自动进行请求发送    start_urls = ["http://www.baidu.com/","https://www.sogou.com"]    # 用于数据解析:response参数表示的就是请求成功后的响应对象    def parse(self, response):        print(response)        pass

        使用指令scrapy crawl main --nolog,输出内容就不会输出多余的内容,只输出打印的内容

        如果里面的代码输入错误,运行加上–nolog后不会有输出,看不出报错

        有个好方法,运行不用加–nolog,在settings.py里面添加LOG_LEVEL='ERROR',如果输入错误,就会报ERROR,如果没错,输出内容和上面运行带上–nolog一样,这里就不用加–nolog

        三、scrapy数据解析

        首先创建项目

        scrapy startproject firstcd firstscrapy genspider main www.xxx.com

        修改settings.py文件的ROBOTSTXT_OBEY = True改为False,才会有输出,添加LOG_LEVEL='ERROR'

        在将注释的USER_AGENT取消注释,在页面中复制该内容到这个变量中

        修改main.py文件

        import scrapyclass MainSpider(scrapy.Spider):    name = "main"    # allowed_domains = ["www.xxx.com"]    start_urls = ["http://www.baidu.com/"]    def parse(self, response):        # 解析数据        # xpath返回的是列表,列表元素一定是Selector类型的对象        p_list = response.xpath('//p')        for p in p_list:            # extract可以将selector对象中data参数存储的字符串提取出来(可以是列表)            print(p.extract())

        执行scrapy crawl main 就会将解析的数据输出

        关于Xpath使用请看:https://blog.csdn.net/weixin_46287157/article/details/116432393

        四、基于终端指令的持久化存储

        1、基于终端指令

        只可以将parse方法的返回值存储到本地的文本文件中

        基于上面解析的数据,将要保存的数据保存在datas中,然后return返回

        再执行指令scrapy crawl main -o ./a.csv,就可以将返回的datas数据保存在a.csv中(要加-o参数保存文件,也可以./a,txt)

        注意:持久化存储的文本类型只可以为json, jsonlines, jsonl, jl, csv, xml, marshal, pickle

        import scrapyclass MainSpider(scrapy.Spider):    name = "main"    allowed_domains = ["www.baidu.com"]    start_urls = ["http://www.baidu.com/"]    def parse(self, response):        datas = []        # 解析数据        # xpath返回的是列表,列表元素一定是Selector类型的对象        p_list = response.xpath('//p[@]/p')        for p in p_list:            # extract可以将selector对象中data参数存储的字符串提取出来(可以是列表)            datas.append(p.xpath('./p').extract())        return datas

        2、基于管道

        首先需要创建项目:

        1、打开pycharm的terminal2、scrapy startproject first3、cd first4、scrapy genspider main www.xxx.com5、修改settings.py里面的ROBOTSTXT_OBEY = True改为False并添加LOG_LEVEL='ERROR'6、scrapy crawl main

        接着需要在主函数(main.py文件)中进行数据解析,main.py内容如下

        import scrapyfrom first.items import FirstItemclass MainSpider(scrapy.Spider):    name = "main"    # allowed_domains = ["www.xxx.com"]    start_urls = ["https://www.gushiwen.cn/"]    def parse(self, response):        # 解析数据        # xpath返回的是列表,列表元素一定是Selector类型的对象        p_list = response.xpath('/html/body/p[2]/p[1]/p')        for p in p_list:            # extract可以将selector对象中data参数存储的字符串提取出来(可以是列表)            # 解析诗歌标题和内容            # 加个if判断,如果解析到的不为空,就进行存储            if len(p.xpath('./p[1]/p[1]/a/b/text()')) != 0 and len(p.xpath('./p[1]/p[2]/text()')) !=0:            # 解析数据                title = p.xpath('./p[1]/p[1]/a/b/text()')[0].extract()                content = p.xpath('./p[1]/p[2]/text()')[0].extract()

        然后在item类中定义相关的属性,将解析的数据存储到item类型的对象(items.py里面有个FirstItem类,可以实例化对象,即item类的实例对象)。修改items.py文件,定义相关属性,比如诗歌、内容,将解析到的数据封装到item对象中:

        class FirstItem(scrapy.Item):    # define the fields for your item here like:    # name = scrapy.Field()    title = scrapy.Field()    content = scrapy.Field()    pass

        用item实例化对象后,这个对象就能取得title和content。将item类型的对象提交给管道进行持久化存储操作。pipelines.py中定义了FirstPipeline类,专门用来处理item类型对象。在管道类的process_item中要将其接受到的item对象中存储的数据进行持久化存储操作

        # 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 interfacefrom itemadapter import ItemAdapterclass FirstPipeline:    fp = None    # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次    def open_spider(self, spider):        print('开启爬虫')        self.fp = open('./a.txt', 'w', encoding='utf-8')    # 用来处理item类型对象    # 该方法可以接收爬虫文件提交过来的item对象    # 该方法每接收到一个人item就会被调用一次    # 如果把打开关闭文件放这,则需要多次打开关闭文件,则另外创建函数,减少打开关闭文件次数    def process_item(self, item, spider): # item为item对象        title = item['title']        content = item['content']        self.fp.write(title+':'+content+'\n')        return item    def close_spider(self, spider):        print('结束爬虫')        self.fp.close()

        在配置文件setting.py中开启管道,即取消管道的注释

        # Configure item pipelines# See https://docs.scrapy.org/en/latest/topics/item-pipeline.htmlITEM_PIPELINES = {   "first.pipelines.FirstPipeline": 300,}

        最后在主函数main.py中添加调库及将解析的数据存储到item类型的对象和将item提交给管道的代码

        import scrapyfrom first.items import FirstItemclass MainSpider(scrapy.Spider):    name = "main"    # allowed_domains = ["www.xxx.com"]    start_urls = ["https://www.gushiwen.cn/"]    def parse(self, response):        # 解析数据        # xpath返回的是列表,列表元素一定是Selector类型的对象        p_list = response.xpath('/html/body/p[2]/p[1]/p')        for p in p_list:            # extract可以将selector对象中data参数存储的字符串提取出来(可以是列表)            # 解析诗歌标题和内容            # 加个if判断,如果解析到的不为空,就进行存储            if len(p.xpath('./p[1]/p[1]/a/b/text()')) != 0 and len(p.xpath('./p[1]/p[2]/text()')) !=0:                title = p.xpath('./p[1]/p[1]/a/b/text()')[0].extract()                content = p.xpath('./p[1]/p[2]/text()')[0].extract()                # 将解析的数据存储到item类型的对象                item = FirstItem()                item['title'] = title                item['content'] = content                # 将item提交给管道,进行数据存储                yield item

        最后运行程序:scrapy crawl main

        3、数据同时保存至本地及数据库

        举例:将爬取的数据一份存到本地,一份存到数据库

        在上面代码的基础上,再在管道中定义多个管道类,一个类制定存储到某个地方(一个存储到本地,一个存储到数据库)

        在piplines.py中新增如下类

        # 导入数据库# import pymysql# 管道文件中一个管道类对应将一组数据存储到一个平台或者载体中class mysqlPileLine(object):    conn = None    cursor = None    def open_spider(self, spider):        self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='123456', db='qiubai', charset='utf8')    def process_item(self, item, spider):        self.cursor =self.conn.cursor()        try:           self.cursor.execute('insert into qiubai values("%s","%s")'%(item["title"],item["content"]))           self.conn.commit()        except Exception as e:            pritn(e)            self.conn.rollback()        return item    def close_spider(self, spider):        self.cursor.close()        self.conn.close()

        在settings.py中开启管道,添加个优先级

        # Configure item pipelines# See https://docs.scrapy.org/en/latest/topics/item-pipeline.htmlITEM_PIPELINES = {    # 300表示优先级,数值越小,优先级越高    "first.pipelines.FirstPipeline": 300,    "first.pipelines.mysqlPileLine": 301,}

        爬虫文件提交的item类型的对象最终会提交给先执行的类(优先级高的类)。在优先级高的里面添加return item,return就会传递给下一个即将执行的管道类,pipelines.py优先级高的类中给一个函数添加return

            def process_item(self, item, spider): # item为item对象        title = item['title']        content = item['content']        self.fp.write(title+':'+content+'\n')        # return就会传递给下一个即将执行的管道类        return item

        管道文件中一个管道类对应的是将数据存储到一个平台。爬虫文件提交的item只会给管道文件中第一个被执行的管道类接收(优先级高的)。process_item中的return item表示将item传递给下一个即将被执行的管道类

        4、基于spider爬取某网站各页面数据

        以某网站为例,对某网站的全部页面(有分页栏)对应的页面进行爬取,这里需要获取所有页面的URL,并将其加入到start_url中,然后进行请求发送

        首先创建项目并初始化操作

        1、打开pycharm的terminal2、scrapy startproject first3、cd first4、scrapy genspider main www.xxx.com5、修改settings.py里面的ROBOTSTXT_OBEY = True改为False并添加LOG_LEVEL='ERROR'6、scrapy crawl main  (最后一步运行)

        然后编辑main.py文件

        import scrapyclass MainSpider(scrapy.Spider):    name = "main"    # allowed_domains = ["www.xxx.com"]    # 第一个页面    start_urls = ["https://www.woyaogexing.com/touxiang/katong/new/index.html"]        # 生成一个通用的url    # %d可以被page_num取代    url = 'https://www.woyaogexing.com/touxiang/katong/new/index_%d.html'    # 页码数    page_num = 2    def parse(self, response):        # 解析数据        p_list = response.xpath('/html/body/p[3]/p[3]/p[1]/p[2]/p')        for li in p_list:            img_name = li.xpath('./a[2]/text()')[0].extract()            print(img_name)        # 递归        if self.page_num 'item': item})        # 分页操作,爬取前5页数据        if self.page_num     # 300表示优先级,数值越小,优先级越高    "first.pipelines.imgPipeline": 300,}# 在配置文件末尾添加文件存储目录IMAGES_STORE = './imgs'    "middlePro.middlewares.MiddleproDownloaderMiddleware": 543,}    "wangyiPro.middlewares.WangyiproDownloaderMiddleware": 543,}# Configure item pipelines# See https://docs.scrapy.org/en/latest/topics/item-pipeline.htmlITEM_PIPELINES = {    "wangyiPro.pipelines.WangyiproPipeline": 300,}'item':item})    # 解析新闻内容    def parse_detail(self, response):        content = response.xpath('').extract()        content = ''.join(content)        item = response.mate['item']        item['content'] = content        yield item    def close(self, spider):        self.bro.quit()'scrapy_redis.pipelines.RedisPipeline':400}# 指定调度器# 增加一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据,从而实现请求取重的持久化存储DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"# 使用scrapy_redis组件自己的调度器SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重指纹的set,如果TrueSCHEDULER_PERSIST = True# 指定redis服务器REDIS_HOST = 'redis服务器ip地址'  # 写成redis远程服务器的ipREDIS_PORT = 6379            'name':item['name']        }        self.conn.lpush('movieData', dic)        return item

上一篇:自己的服务器怎么宣传?

下一篇:揭秘图片局部放大技巧,轻松展现细节之美!