Scrapy
Scrapy 是一个位了爬取网站数据, 提取数据结构性数据而编写的应用框架, 少量代码, 就能快速爬取, 使用了 Twisted 异步网络框架, 加快我们下载速度!
工作流程
制作 Scrapy 爬虫 一共需要 4 步:
新建项目 (scrapy startproject xxx): 新建一个新的爬虫项目
明确目标 (编写 items.py): 明确你想要抓取的目标
制作爬虫 (spiders/xxspider.py): 制作爬虫开始爬取网页
存储内容 (pipelines.py): 设计管道存储爬取内容
Scrapy Engine(引擎): 负责 Spider,ItemPipeline,Downloader,Scheduler 中间的通讯, 信号, 数据传递等.
Scheduler(调度器): 它负责接受引擎发送过来的 Request 请求, 并按照一定的方式进行整理排列, 入队, 当引擎需要时, 交还给引擎.
Downloader(下载器): 负责下载 Scrapy Engine(引擎)发送的所有 Requests 请求, 并将其获取到的 Responses 交还给 Scrapy Engine(引擎), 由引擎交给 Spider 来处理,
Spider(爬虫): 它负责处理所有 Responses, 从中分析提取数据, 获取 Item 字段需要的数据, 并将需要跟进的 URL 提交给引擎, 再次进入 Scheduler(调度器).
Item Pipeline(管道): 它负责处理 Spider 中获取到的 Item, 并进行进行后期处理 (详细分析, 过滤, 存储等) 的地方.
Downloader Middlewares(下载中间件): 你可以当作是一个可以自定义扩展下载功能的组件.
Spider Middlewares(Spider 中间件): 你可以理解为是一个可以自定扩展和操作引擎和 Spider 中间通信的功能组件(比如进入 Spider 的 Responses; 和从 Spider 出去的 Requests)
Scrapy 的运作流程
代码写好, 程序开始运行...
1 引擎: Hi!Spider, 你要处理哪一个网站?
2 Spider: 老大要我处理 http://xxxx.com/ .
3 引擎: 你把第一个需要处理的 URL 给我吧.
4 Spider: 给你, 第一个 URL 是 http://xxxxxxx.com/ .
5 引擎: Hi! 调度器, 我这有 request 请求你帮我排序入队一下.
6 调度器: 好的, 正在处理你等一下.
7 引擎: Hi! 调度器, 把你处理好的 request 请求给我.
8 调度器: 给你, 这是我处理好的 request
9 引擎: Hi! 下载器, 你按照老大的下载中间件的设置帮我下载一下这个 request 请求
10 下载器: 好的! 给你, 这是下载好的东西.(如果失败: sorry, 这个 request 下载失败了. 然后引擎告诉调度器, 这个 request 下载失败了, 你 记录一下, 我们待会儿再下载)
11 引擎: Hi!Spider, 这是下载好的东西, 并且已经按照老大的下载中间件处理过了, 你自己处理一下 (注意! 这儿 responses 默认是交给 def parse() 这个函数处理的)
12 Spider:(处理完毕数据之后对于需要跟进的 URL),Hi! 引擎, 我这里有两个结果, 这个是我需要跟进的 URL, 还有这个是我获取到的 Item 数据.
13 引擎: Hi ! 管道 我这儿有个 item 你帮我处理一下! 调度器! 这是需要跟进 URL 你帮我处理下. 然后从第四步开始循环, 直到获取完老大需要全部信息.
14 管道调度器: 好的, 现在就做!
注意! 只有当调度器中不存在任何 request 了, 整个程序才会停止,(也就是说, 对于下载失败的 URL,Scrapy 也会重新下载.)
入门实例爬取(腾讯招聘)
准备环境:
pip install scrapy
1)创建项目
scrapy startproject myspider
2)创建仪个爬虫
scrapy genspider itcast(爬虫名字) "itcast.cn"(限制网站的范围)
3)启动爬虫
scrapy crawl itcast
代码:
- ### 设置 item 字段 ###
- import scrapy
- class MyspiderItem(scrapy.Item):
- title = scrapy.Field()
- position = scrapy.Field()
- time = scrapy.Field()
- address = scrapy.Field()
- ### 设置 spiders 目录下的爬虫脚本, 可以设置多个 ##
VIM spiders/itcast.py
- # -*- coding: utf-8 -
- import scrapy
- import sys
- #之前设置好的 items 导入进来
- from myspider.items import MyspiderItem
- class ItcastSpider(scrapy.Spider):
- #spider.name 可以用于判断
- name = 'itcast'
- #限制范围
- allowed_domains = ['tencent.com']
- start_urls = ['https://hr.tencent.com/position.php?lid=2218&tid=87']
- #parse 方法不能修改, 必须有
- def parse(self, response):
- tb_list = response.xpath("//table[@class='tablelist']/tr")[1:-1]
- for tr in tb_list:
- #字典对象
- item = MyspiderItem()
- item['title'] = tr.xpath("./td[1]/a/text()").extract_first()
- item['position'] = tr.xpath("./td[2]/text()").extract_first()
- item['address'] = tr.xpath("./td[4]/text()").extract_first()
- item['time'] = tr.xpath("./td[5]/text()").extract_first()
- yield item
- #翻页
- next_url = response.xpath("//a[@id='next']/@href").extract_first()
- print(next_url)
- if next_url != "javascript:;":
- next_url = "https://hr.tencent.com/" +next_url
- print(next_url)
- #下一页请求, scrapy 封装好的 request 请求
- yield scrapy.Request(
- next_url,
- callback=self.parse
- )
- print("="*30)
- ## 设置存储 pipeline##
VIM pipelines.py
- # -*- coding: utf-8 -*-
- import JSON
- class MyspiderPipeline(object):
- def process_item(self,item,spider):
- #有判断, 以后可以写多个 piiline, 来存储
- if spider.name == "itcast":
- with open('temp.txt','a') as f:
- #item 是一个对象, 要转成字典!
- JSON.dump(dict(item),f,ensure_ascii=False,indent=2)
- ## 设置 setting 配置 ##
开启 pipelines, 可以设置多个
来源: http://www.bubuko.com/infodetail-2896230.html