# scrapy 爬虫学习

  • 开启项目: scrapy startproject example
  • 定义爬虫文件: cd example; scrapy genspider book_psider http://books.toscrape.com/
  • 定义数据最终需要的字段, 修改items.py。
  • 如果不用pipeline处理,则yeild item, 直接 -o 到文件json文件即可。
  • 执行爬虫 scrapy crawl book_spider -o book.json

# 2. 核心概念

# 爬虫组件

组件 描述 类型
ENGINE 引擎,框架核心组件 内部组件
SCHEDULER 调度器 内部组件
DOWNLOADER 下载器 内部组件
SPIDER 爬虫,负责提取页面数据,发起页面请求 用户实现
MIDDLEWARE 中间件,负责对req和res对象的处理 可选组件
ITEM PEIPELINE 数据管道 可选组件

# 爬虫流程

  • request和response,item三个主要对象。
  • 爬虫文件, 利用url构造一个request对象交给 ENGINE
  • ENGINE将request对象加入调度器队列排队,之后取出交给下载器
  • 下载器根据request对象发起http请求,生成response对象,传递到ENGINE。
  • response对象最后送回爬虫文件,由parse函数处理,提取数据成item定义的格式,送回ENGINE
  • 数据最后被送往PIPELINE处理,或者EXPORTER直接导出json、csv等格式。
  • parse可能继续构造request交给ENGINE处理,循环爬取....

# request对象

  • url 参数
  • callback参数
  • method参数, 默认GET
  • headers 请求头
  • body POST参数
  • cookies cookie 字典信息,dict类型
  • meta 元数据字典,dict类型,用于给Pipeline中间件或处理函数传递数据。
  • encoding 默认编码方式 utf8, 如果url和body体是str,就用该参数编码。
  • priority 请求优先级,默认0. 优先级高的先下载。
  • dont_filter ,默认false。 对同一个请求,只会下载一次,如果需要重复请求下载,设置为true,比如频繁更新的同一url。
  • errback 请求出现异常的回调函数。
  • 除了url,其他有默认值。我们只需要关心url和callback函数。

# response对象

  • response是一个父类, 具体根据内容可能是TextResponse,HtmlResponse,XmlResponse
  • 请求完成后,根据http响应的content-type确定子类对象。
  • TextResponse是其他两个的父类,三者微小的差别。
  • url,响应的url
  • status http状态码
  • headers 相应头部., 可以get获取response.headers.get("Content-Type")
  • body, 响应征文。bytes类型
  • text 响应正文,str类型。由body使用response.encoding 解码得到。
  • encoding http响应正文的编码, 一般由http响应头部解析出来。
  • request http响应的Reuquest对象。
  • meta 实际是response.request.meta , 通过response.meta 使用。
  • selector 选择器,用于提取数据。
  • xpath xpath选择器,用于提取数据。
  • css css选择器。
  • urljoin(url) 构造出绝对路径url。

# 3. 编写爬虫文件 spider

  • 编写 start_requests函数
  • 编写parse函数

# 4. 选择器

# Selector选择器(CSS)

  • 可以直接通过html文本作为Selector参数
  • 可以直接用Reponse响应对象作为Selector的response参数 Selector(response=response)
  • 构造了对象,可以用xpath方法或者css方法, 返回的是list, 里面还是子的Selector对象,可以继续迭代。
  • Selector对象可以有以下方法取数据
    • selector.xpath(".//li")[0].extract() 返回整个li标签 <li>xxxxx</li>
    • 选择器列表使用extract_first 相当于直接取第一个选择器的内容 == text() 然后extract()[0]
    • xpath获得的列表,可以直接使用.re(), 会自动将列表中每个元素都正则过滤一下。
    • 列表的re_first() 方法同样直接去第一个内容,并匹配正则。
    • 为了方便,response 会自动创建selector对象, 而且定义了xpath和css方法,实际调用的是selector对象的xpath和css方法。

# xpath 选择器

  • html也属于xml文档,都是树结构
  • / 跟路径
  • ./当前节点
  • ..当前节点的父节点
  • E 选择当前节点中的全部E元素
  • //E 选择html下的全部E元素
    • 全部元素
  • text() 元素的文本内容
  • @attr 元素的某个属性 比如 @href
  • @* 全部属性
  • /div[@id] 含有id属性的div
  • /div[@id="xxx"] id等于xxx的div
  • /div[@class="xxx"] class等于xxx的div
  • //a[last()] 最后一个a
  • //a[position() <=3] 选中前三个
  • string(路径).extract() 会把列表中内容连接成一个字符串,放入列表。
  • contains(x, y ) 判断x中是否包含y

# CSS 选择器

  • * 全部元素
  • E 选中E元素
  • E1,E2 选中E1,E2元素
  • E1 E2 选中E1后代,和E1同一级的元素中的E2元素
  • E1>E2 E1子元素中的E2
  • .cls 选中class属性是cls的元素
  • #idd 选中id为idd的元素
  • [href] 包含href属性的元素
  • [href="www"] href属性等于www的元素
  • [href~="www"] href属性值不等于www的元素
  • E:nth-child(n) 选择E元素,E元素是他爹的第n的子元素
  • E:nth-last-child(n) 选择E,且E是她爹的倒数第n个元素
  • E:first-child 选择E,且E必须是她爹的第一个元素
  • E:last-child 选择E, 且E是她爹的倒数第一个元素
  • E:empty 选中没有子元素的E元素
  • E:text 选中E的文本内容

我练习scrapy的代码