爬虫之Scrapy框架介绍
Scrapy介绍
Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。
框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
Scrapy 使用了 Twisted异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。
Scrapy架构图
Scrapy Engine(引擎): 用来处理整个系统的数据流处理, 触发事务(框架核心)
Scheduler(调度器): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
Spider(爬虫):爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
Item Pipeline(管道):负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
Downloader Middlewares(下载中间件):位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
Spider Middlewares(调度中间件):介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。
Scrapy运行流程
- 首先,引擎从调度器中取出一个链接(URL)用于接下来的抓取
- 引擎把URL封装成一个请求(Request)传给下载器,下载器把资源下载下来,并封装成应答包(Response)
- 然后,爬虫解析Response
- 若是解析出实体(Item),则交给实体管道进行进一步的处理。
- 若是解析出的是链接(URL),则把URL交给Scheduler等待抓取
安装
Linux安装:
pip3 install scrapy
Windows安装:
# 1. pip3 install wheel # 2. 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted # 3. 进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl # 4. pip3 install pywin32 # 5. pip3 install scrapy
命令行工具
# 1 查看帮助 scrapy -h scrapy <command> -h # 2 有两种命令:其中Project-only必须切到项目文件夹下才能执行,而Global的命令则不需要 Global commands: startproject #创建项目 genspider #创建爬虫程序 settings #如果是在项目目录下,则得到的是该项目的配置 runspider #运行一个独立的python文件,不必创建项目 shell #scrapy shell url地址 在交互式调试,如选择器规则正确与否 fetch #独立于程单纯地爬取一个页面,可以拿到请求头 view #下载完毕后直接弹出浏览器,以此可以分辨出哪些数据是ajax请求 version #scrapy version 查看scrapy的版本,scrapy version -v查看scrapy依赖库的版本 Project-only commands: crawl #运行爬虫,必须创建项目才行,确保配置文件中ROBOTSTXT_OBEY = False check #检测项目中有无语法错误 list #列出项目中所包含的爬虫名 edit #编辑器,一般不用 parse #scrapy parse url地址 --callback 回调函数 #以此可以验证我们的回调函数是否正确 bench #scrapy bentch压力测试
Scrapy框架官方网址:http://doc.scrapy.org/en/latest
Scrapy中文维护站点:http://scrapy-chs.readthedocs...
目录结构
project_name/ scrapy.cfg # 项目的主配置信息,用来部署scrapy时使用,爬虫相关的配置信息在settings.py文件中。 project_name/ __init__.py items.py # 设置数据存储模板,用于结构化数据,如:Django的Model pipelines.py # 项目管道文件,如:一般结构化的数据持久化 settings.py # 配置文件,如:递归的层数、并发数,延迟下载等。 spiders/ # 爬虫目录,如:创建文件,编写爬虫规则 __init__.py 爬虫1.py 爬虫2.py 爬虫3.py
注意:
1. 一般创建爬虫文件时,以网站域名命名
2. 默认只能在终端执行命令,为了更便捷操作:
如果想在pycharm中执行需要做:
#在项目目录下新建:entrypoint.py from scrapy.cmdline import execute # execute(['scrapy', 'crawl', 'amazon','--nolog']) #不要日志打印 # execute(['scrapy', 'crawl', 'amazon']) #我们可能需要在命令行为爬虫程序传递参数,就用下面这样的命令 #acrapy crawl amzaon -a keyword=iphone8 execute(['scrapy', 'crawl', 'amazon1','-a','keyword=iphone8','--nolog']) #不要日志打印 # execute(['scrapy', 'crawl', 'amazon1'])
项目实战
scrapy startproject Qiubai # 创建项目 cd Qiubai # 进入项目目录 scrapy genspider qiubai www.qiushibaike.com # 应用名称 爬取网页的起始url
2 编写爬虫文件:在步骤2执行完毕后,会在项目的spiders中生成一个应用名的py爬虫文件,文件源码如下:
import scrapy class QiubaiSpider(scrapy.Spider): name = 'qiubai' # 应用名称 # 允许爬取的域名(如果遇到非该域名的url则爬取不到数据) allowed_domains = ['https://www.qiushibaike.com/'] start_urls = ['https://www.qiushibaike.com/'] # 起始爬取的url def parse(self, response): # xpath为response中的方法,可以将xpath表达式直接作用于该函数中 odiv = response.xpath('//div[@id="content-left"]/div') content_list = [] # 用于存储解析到的数据 for div in odiv: # xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。 author = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0].extract() content=div.xpath('.//div[@class="content"]/span/text()')[0].extract() # 将解析到的内容封装到字典中 dic={ '作者':author, '内容':content } # 将数据存储到content_list这个列表中 content_list.append(dic) return content_list
3 设置修改settings.py配置文件相关配置,修改内容及其结果如下:
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' #伪装请求载体身份 ROBOTSTXT_OBEY = False # 可以忽略或者不遵守robots协议
4 执行爬虫程序:
scrapy crawl 爬虫名称 # 该种执行形式会显示执行的日志信息 scrapy crawl 爬虫名称 --nolog # 该种执行形式不会显示执行的日志信息
最后
今天是情人节,祝大家情人节快乐
有对象的已经去跟对象去约会了,爱学习的才会跟代码相伴(比如我)
送大家一段 python 的情人节代码吧:
print("\n".join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 <= 0 else ' ') for x in range(-30, 30)]) for y in range(30, -30, -1)]))
好奇的去copy运行一下吧~