- Scrapy主要组件:
- 引擎(Scrapy)—-类似于中央cpu,发动机,安排各个部门的任务
- 调度器(Scheduler)—-队列,决定下一个抓取的URL
- 下载器(Downloader)—下载网页的内容(资源),并Response给Spider{此下载器是建立在twisted这个异步模型上} ________twisted异步模型????有待学习
- 爬虫(Spiders)—获取自己需要的信息,所谓实体(item),也可能是链接(URL)接着发送给Scheduler
- 项目管道(Pipeline )—负责处理爬虫从网页中抽取的实体,主要功能是持久化实体,验证实体的有效性,清楚不需要的数据。 爬虫解析–>项目管道–>经过几个特定的次序处理数据
- 下载器中间件(Downloader Middlewares)
- 爬虫中间件(Spider Middlewares)
- 调度中间件(Scheduleer Middlewares)
2.了解scrapy的运行流程:
- 引擎从调度器中取出一个连接(URL)用于接下来的抓取
- 引擎把URL封装成一个请求(Request)用于接下来的抓取
- 下载器把资源下载下来,并封装成应答包(Response)
- 爬虫解析Response
- 解析出实体(item),则交给实体管道进行进一步处理
- 解析出的是链接(URL),则把URL交给调度器等待抓取
3.Scrapy项目基本流程
开始项目指令(默认的项目结构)
scrapy startproject myproject
scrapy.cfg
#项目的配置文件
myproject/__init__.py items.py pipelines.py settings.py spiders/ __init__.py spider1.py spider2.py
①定义item:保存爬取到的数据的容器(下载器–>Spider–>item);使用方法与python字典类似,并且提供额外的保护机制来避免拼写错误导致的未定义字段错误/数据存储模板,结构化数据
import scrapy
class DmozItem(scrapy.Item):
title=scrapy.Field()
link=scrapy.Field()
desc=scrapy.Field()
上诉这段代码为item进行数据建模。可以理解成我们要从dmoz.org(一个目录搜索网站)中通过下载器下载—–>spider解析后获得实体—>item 即名字,URL以及网站的描述;
2.Spider(爬虫)编写
spider即用户从若干个网站中爬取数据,逻辑包含以下部分,一般以要爬取的网站域名命名
- URL—爬取网站的域名
- 对网页中的链接以及如何分析页面中的
- 提取生成item的方法
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes" #用于区别Spider ,名字必须唯一 ,不同的Spider
def start_requests(self): #定义Spider爬取的URL列表。 第一个被获取到页面将是其中之一。后续的URL则从初始的URL获取到的数据中提取。
urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse) #request请求,response回应 ,callback回调函数
# start_urls = [
#'http://quotes.toscrape.com/page/1/',
#'http://quotes.toscrape.com/page/2/',
#] 此注释内容和start_request效果一致,更加简洁
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
上述代码中把爬虫文件封装成一个类(继承Scrapy.spiders.Spider)定义三个属性:
- name —必须定义,爬虫名,如果没有会报错
- parse —函数名不可更改,因为源码中默认callback函数的函数名就是parse。 url完成下载后生成的Response对象将会作为唯一的参数传递给该函数 –> parse(response data) – > 提取数据(生成item)以及需进一步处理的URL的 Request 对象 为scrapy的默认回调函数,哪怕你没有清晰指出
- 个人理解: 下载器下载了整个HTML –> parse 进行处理获取个人的需求item或者URL
- start_requests (start_urls) —-需要爬取的URL。放在列表中,Scrapy源码是一个FOR循环,从上到下,使用生成器迭代将URL发送给下载器下载url的html。
3.运行指令
进入Scrapy所在目录,运行命令:
scrapy crawl + 爬虫名 --nolog(不显示日志)
如有报错请参考
http://blog.youkuaiyun.com/qq_30717683/article/details/68943899
- 从输出的log中可以看出 为每个URL创建scrapy.Request对象,并将parse方法作为回调函数(callback)赋值个Request
- Request对象经过调度,执行生成 scrapy.http.Response 对象并送回给spider parse() 方法。—parse()方法处理返回的Response
4.scrapy 查询语法(从HTML提取数据)
- 当我们爬取到大量网页时,在不用框架的时候,一般是用正则表达式匹配我们所需要的东西,比如说图片的下载地址,文章的content,好评数等。
scrapy内部语法,可以从HTML中查询需要的标签、标签内容、标签属性等
Selectors(选择器——就是用来匹配你说需要的东西) 基于Xpath和CSS表达机制
- xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。
- css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.
- extract(): 序列化该节点为unicode字符串并返回list。
- re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。
在shell中尝试Selector 选择器是不错的学习路径(HTML作为Response对象返回 并提前初始化变量 Sel ,下面对其进行操作)
- 指令 scrapy shell + “URL 地址”__在Windows中需要使用“url”双引号否则报错 : 得到一个Response变量
- reponse.body :输出HTML body部分
- reponse.headers : 输出HTML headers部分
- response.selector : 获取一个用于返回数据的Selector(选择器);以及映射到 response.selector.xpath() 、 response.selector.css() 的 快捷方法(shortcut): response.xpath() 和 response.css() 。
- 指令 scrapy shell + “URL 地址”__在Windows中需要使用“url”双引号否则报错 : 得到一个Response变量
提取数据
在终端输入response.body 观察HTML源码确定合适的Xpath表达式 **(浏览器中F12一样效果更加直观)**xpath更强大,推荐使用
- response.xpath(“//ul/li”)
- 网站的描述:response.xpath(‘//ul/li/text()’).extract()
- 网站的标题:response.xpath(‘//ul/li/a/text()’).extract()
- 网站的链接:response.xpath(‘//ul/li/a/@href’).extract()
for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
eg1 :
response.css(“title”) --> SelectorList
response.css("title::text").extract() -->list
response.css("title::text").extract_first() #搜索第一个,当没有返回值时返回NONE,避免IndexError
当没有爬取到数据时,尽量返回一些其他信息- eg2 :
response.css("title::text").re("") #结合正则使用
- 推荐使用Selector Gadget find CSS selector 适用多种browsers
5.保存爬取到的数据
scrapy crawl dmoz -o items.json