scrapy
-
网络爬虫核心工作
- 通过网络向指定的 URL 发送请求,获取服务器响应内容
- 使用某种技术(如正则表达式、XPath 等)提取页面中我们感兴趣的信息
- 高效地识别响应页面中的链接信息,分析这些链接递归执行此处介绍的第 1、2、3 步
- 使用多线程有效地管理网络通信交互
-
分析
- 正则表达式设计的初衷主要是处理文本信息
- HTML 文档不仅是文本文档,而且是结构化文档,使用XPath更合适
- 多线程管理,核心工作通用,应由框架来完成
-
scrapy包
- 专业的 Twisted 包(基于事件驱动的网络引擎包)高效地处理网络通信
- lxml(专业的 XML 处理包),cssselect 高效地提取 HTML 页面的有效信息
- 提供了有效的线程管理,开发者只要使用 XPath 或 css 选择器定义自己感兴趣的信息
-
依赖包
Twisted
:为 Python 提供的基于事件驱动的网络引擎包lxml
:一个处理 XML、HTML 文档的库,比 Python 内置的 xml 模块更好用pyOpenSSL
:Python 用于支持 SSL(Security Socket Layer)的包cryptography
:Python 用于加密的库
-
scrapy核心组件
- 调度器 负责使用下载中间件从网络上下载资源
- 下载器 下载数据后由scrapy引擎自动提交给蜘蛛
- 蜘蛛 由开发者实现,蜘蛛提取到的信息由scrapy引擎以item对象的形式转交给Pipeline
- pipeline 接收Item对象,可将这些信息写入文件或数据库中
- Item 类就是一个 DTO(数据传输对象)
- pipelines 负责处理爬取到的信息
-
scrapy shell
- 先用命令窗口 用XPath 从 HTML 文档中提取信息
scrapy shell url
使用 Scrapy 提供的 shell 调试工具来抓取该页面中的信息scrapy shell -s USER_AGENT='Mozilla/5.0' url
让 Scrapy 伪装成 Firefox 来开启 shell 调试- 上述命令成功会进入shell,并提供scrapy变量,以便调试
scrapy,crawler,item,request,response,settings,spider
- 函数
fetch(url),fetch(req),shelp(),veiw(response)
response.xpath ('//div[@class="job-primary"]/div/h3/a/div/text()').extract()
提取节点内容- shell根据response提前初始化了变量 sel,该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)
- shell载入后,得到一个包含response数据的本地response变量
response.body,response.headers
response.selector.xpath()
映射快捷方法response.xpath()
response.selector.css()
快捷方法 ``
- shell根据response提前初始化了变量 sel,该selector根据response的类型自动选择最合适的分析规则(XML vs HTML)
-
xpath简化写法
表达式 作用 nodename 匹配此节点的所有内容 / 匹配根节点 // 匹配任意位置的节点 . 匹配当前节点 … 匹配父节点 @ 匹配属性 nodename[expr] 对该节点进行谓词限制 text() 匹配文件节点对象 @attr 匹配属性节点 -
Scrapy项目开发流程
- 定义 Item 类 (确定信息呈现结构,读)
- 生成项目骨架
scrapy startproject <project_name> [project_dir]
- 数据传输对象(DTO)的
- 生成项目骨架
- 编写 Spider 类 (抓节点,多个抓取源)核心
scrapy genspider [options] <name> <domain>
进入项目后执行,生成蜘蛛类- 将要爬取的各页面 URL 定义在
start_urls
列表中 - 在 parse(self, response) 方法中通过 XPath 或 CSS 选择器提取项目信息
- 该返回的是一个迭代生成器
yield
, 类似于goto语句,即可以中断当前函数体,让渡控制权
- 该返回的是一个迭代生成器
- 编写 pipelines.py 文件(存)
- 该文件负责将所爬取的数据写入文件或数据库中
- 实现
process_item(self, item, spider)
方法
- 配置settings.py
- 配置User-Agent
- 配置使用piepline
- 定义 Item 类 (确定信息呈现结构,读)
-
selector
基本方法xpath()
传入xpath表达式,返回表达式所有对应的所有节点的selector list
列表css()
传入CSS表达式extract()
序列化该节点为unicode字符串并返回listre()
根据传入的正则表达式对数据进行提取,返回unicode字符串list列表
-
小记
- 需要将源码保存为utf-8
- 生成项目 -> 进入项目生成蜘蛛
extract(), extract_first()
节点对象方法,提取多个或单个信息- 数据流向 蜘蛛–> pipeline 入库…
爬取【汉乡】小说代码
- 用scrapy1.6创建 glance项目
- 写下如下代码,运行
scrapy crawl hanxiang
得到汉乡.txt小说免费章节
- 蜘蛛
# -*- coding: utf-8 -*-
# spiders/hanxiang.py
import scrapy
class HanxiangSpider(scrapy.Spider):
name = 'hanxiang'
allowed_domains = ['qidian.com']
start_urls = ['https://book.qidian.com/info/1010136878']
def parse(self, response):
# 汉乡 当所选select对象存在多个链接时,需要指定单一的属性节点
yield response.follow(response.xpath('//a[(@id = "readBtn")]/@href').get(), callback=self.parse_chapter)
def parse_chapter(self, response):
yield {
'chapterName': response.css('h3.j_chapterName::text').get(),
'content': response.css('.j_readContent ::text').getall()
}
next_page = response.css('#j_chapterNext').xpath('@href').get()
if next_page is not None:
try:
# 不是vip章节才进行下一步抓取,index方法未找到字符串则抛异常 ValueError
next_page.index('vipreader')
except ValueError:
yield response.follow(next_page, callback=self.parse_chapter)
- 管道
# 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
class GlancePipeline(object):
def process_item(self, item, spider):
with open('汉乡.txt', 'a+', encoding='utf-8') as f:
f.write(item['chapterName'])
f.write('\n'.join( s for s in item['content']))
f.write('\n')
return item
- 配置
ITEM_PIPELINES = {
'glance.pipelines.GlancePipeline': 300,
}