Python—Scrapy爬虫框架

    xiaoxiao2024-10-17  71

    scrapy的github地址:https://github.com/scrapy/scrapy

     

    scrapy

    scrapy是一个功能强大的网络爬虫框架

    scrapy不是一个函数功能库,而是一个爬虫框架

    requesus+beautifulsoup库 和 scrapy爬虫比较

    requesus+beautifulsoup和Scrapy是python爬虫的两种技术路线

          ①requests和beautifulsoup都是库,scrapy是框架

          ②scrapy框架中可以加入requests和beautifulsoup

          ③scrapy基于twisted,性能是最大的优势(scrapy是基于异步结构设计,可以同时向多个网站发起爬取请求)

          ④scrapy方便扩展,提供了很多内置的功能

          ⑤scrapy内置的css和xpath selector非常方便,beautifulsoup最大的缺点就是慢

     

     

          网络爬虫爬取的快与慢,要结合特定的情况来考虑。对于一些很成熟的网站,都有反爬技术,反爬技术反而要求爬虫爬取的速度不能太快,否则就会被反爬技术发现并屏蔽ip

     

    选择哪个技术路线

          非常小的需求,requests库。

         不太小的需求,Scrapy框架。

         定制程度很高的需求(不考虑规模),自搭框架,requests>Scrapy。

     

    scrapy爬虫框架

    scrapy爬虫框架一共包含7个部分,称为“5+2”结构。

    5个部分是框架的主体部分,另外包含2个中间件

     

    scrapy其实是大量借鉴了django的设计理念

     

    中间件之一

    中间件之二

     

    spiders是整个爬虫框架最核心的一个单元

     

     

    scrapy工程目录结构

          scrapy.cfg 部署Scrapy爬虫的配置文件——将爬虫放在特定的服务器上,并且在服务器配置好相关的操作接口。对于本机使用的爬虫来讲,不需要改变部署的配置文件

     

         如果希望优化爬虫功能,我们需要修改settings.py中的配置项

     

    spiders文件夹是存放具体的某个网站的爬虫,比如说知乎的爬虫,比如说伯乐在线的爬虫

     

     

     

    scrapy爬虫的常用命令

    scrapy是为持续运行设计的专业爬虫框架,提供操作的Scrapy命令行

    在Scrapy框架下,一个工程是一个最大的单元。一个工程可以相当于一个大的Scapy框架,在一个框架中可以有多个爬虫,每个爬虫相当于框架中的一个spider模块。

     

    示例1

    定义一个工程,名字叫python123demo

     

    在工程中产生一个Scrapy爬虫

    genspider命令——需要用户给出爬虫的名字(demo)以及所爬取的网站(python123.io)

    配置产生的spider爬虫——修改demo.py文件

    # -*- coding: utf-8 -*- import scrapy class DemoSpider(scrapy.Spider): name = 'demo' allowed_domains = ['python123.io'] start_urls = ['http://python123.io/ws/demo.html'] # self是面向对象类所属关系的标记 # response是从网络中返回内容所存储的或对应的对象,我们要把response的内容写到一个html文件中 def parse(self, response): fname = response.url.split('/')[-1] # 从响应的url中提取文件名字作为我们保存在本地的文件名 with open(fname, 'wb') as f: f.write(response.body) self.log('Saved file %s.' % fname) # 经过这样的改造我们的demo.py就能够爬取一个网页并且把网页的内容保存为一个html网页

    运行爬虫

     

    我们看到的demo.py其实是scrapy提供的简化版的代码

     

    yield的关键字的使用

    生成器的使用一般与循环搭配

     

    Scrapy爬虫的基本使用

    Scrapy爬虫的数据类型:

    Request类(向网络上提交请求的内容)Response类(从网络中爬取内容的封装类)Item类(由spider产生的信息封装的类)

    Request类和request库中的request类不是一个定义,但是十分相似

     

     

    实例之股票数据Scrapy爬虫

    stocks.py

    # -*- coding: utf-8 -*- import scrapy import re class StocksSpider(scrapy.Spider): name = 'stocks' #allowed_domains = ['baidu.com']没用 start_urls = ['http://quote.eastmoney.com/stocklist.html'] def parse(self, response): for href in response.css('a::attr(href)').extract(): try: stock = re.findall(r'[s][hz]\d{6}',href)[0] #获取其中的股票代码 url = 'https://gupiao.baidu.com/stock/' + stock + '.html'#生成一个百度股票对应页面的链接 yield scrapy.Request(url,callback=self.parse_stock) #callback给出了处理这个url对应响应的处理函数 except: continue def parse_stock(self,response): infoDict = {} stockInfo = response.css('.stock_bets') name = stockInfo.css('.bets-name').extract()[0] keyList = stockInfo.css('dt').extract() valueList = stockInfo.css('dd').extract() #将提取的信息保存在字典中 for i in range(len(keyList)): key = re.findall(r'>.*</dt>',keyList[i])[0][1:-5] try: val = re.findall(r'\d+\.?.*</dd>',valueList[i])[0][0:-5] except: val = '--' infoDict[key] = val #将股票名称进行更新 infoDict.update( # {'股票名称':re.findall('\s.*\(',name)[0].split()[0] + \ # re.findall('\>.*\<',name)[0][1:-1]}) {'股票名称': re.findall('\s.*\(',name)[0].split()[0] + \ re.findall('\>.*\<',name)[0][1:-1]}) #到此,infoDict这个字典保存了一个股票页面提取的股票名称及相关信息 #下面我们将相关信息给到后续处理的ITEM Pipelines模块 yield infoDict

    pipelines.py

    # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html #这里面的每一个类都是对一个item进行处理的一个过程 class BaidustocksPipeline(object): def process_item(self, item, spider): return item class BaidustocksInfoPipeline(object): def open_spider(self,spider): #对应当一个爬虫被调用时对应的pipeline启动方法 self.f = open('BaiduStockInfo.txt','w') def close_spider(self,spider): #一个爬虫关闭时pipeline对应的方法 self.f.close() def process_item(self,item,spider): #对每一个item项进行处理时对应的方法,也是pipeline中最主体的函数 try: line = str(dict(item)) + '\n' self.f.write(line) except: pass return item

    pipelines.py文件处理完了,这里面我们写了一个新的类,怎样让框架找到这个类呢?需要修改一个配置文件settings.py

    在里面找到ITEM_PIPELINES,修改

    修改前:

    修改后:

    之后用 scrapy crawl stocks  来运行

     

    从东方财富网获得股票的列表,并针对每一个股票列表生成一个百度股票的链接,并向这个百度股票的链接进行信息爬取。对于爬取后的信息,经过spider的处理,我们提取出其中的关键信息形成字典,并且将这个字典以item类的形式给到了item-pipelines进行后续处理

     

    速度优化

    最新回复(0)