CrawlSpiders介绍
- 创建命令: scrapy genspider -t crawl 爬虫名 allow_domain
- 它是Spider的派生类,Spider类的设计原则是只爬取start_url列表中的网页,而CrawlSpider类定义了一些规则(rule)来提供跟进link的方便的机制,从爬取的网页中获取link并继续爬取的工作更适合。
应用场景
- url的规律能够通过正则或xpath表示
- 最终页面有全部数据的时候使用(也不一定是全部 适合就好)
Spiders版本
# -*- coding: utf-8 -*-
import scrapy
import re
class CfSpider(scrapy.Spider):
name = 'cf'
allowed_domains = ['circ.gov.cn']
start_urls = ['http://bxjg.circ.gov.cn/web/site0/tab5240/module14430/page1.htm']
def parse(self, response):
tr_list = response.xpath("//table[@id='ess_ctr14430_ListC_Info_LstC_Info']/tr")
for tr in tr_list:
href = tr.xpath(".//a[@href]/@href").extract_first()
href = "http://bxjg.circ.gov.cn" + str(href)
yield scrapy.Request(
href,
callback=self.parse_detail,
)
next_url = response.xpath("//a[text()='下一页']/@href").extract_first()
print(next_url)
if next_url is not None:
next_url = "http://bxjg.circ.gov.cn" + str(next_url)
yield scrapy.Request(
next_url,
callback=self.parse,
)
def parse_detail(self, response):
item = {}
item["title"] = re.findall(r"<!--TitleStart-->(.*?)<!--TitleEnd-->", response.body.decode())[0]
item["publish_date"] = re.findall(r"发布时间:(.*?) ", response.body.decode())[0]
print(item)
CrawlSpider版本
# -*- coding: utf-8 -*-
import scrapy
# 创建可以提取相应里链接的 LinkExtractor对象
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
import re
class Cf1Spider(CrawlSpider):
name = 'cf1'
allowed_domains = ['circ.gov.cn'] # 域的范围
start_urls = ['http://bxjg.circ.gov.cn/web/site0/tab5240/module14430/page1.htm']
# 定义提取url地址规则
rules = (
# LinkExtractor 链接提取器,提取url地址,提取到的url地址交给parse函数发送请求。
# LinkExtractor 有一个集合(集合是唯一的),在当前响应中提取到的链接会放进去,并进行判重操作,如果有,就不会再提取。
# callback 提取出来的url地址的response会交给callback处理 callback后面必须是字符串
# follow 当前url地址的响应能够重新进入rules(经过rules包含的每一个Rule)来提取url地址。follow和callback看情况而写
# 如果callback为None,follow默认设置为True,否则默认为False。 这种逻辑的原因:不需要callback解析的一般是翻页或者跳板链接,自然需要follow跟进。
# Rule之间不能传递参数 只有手动yield才能通过meta传参
# url地址不完整 crawlspider会自动补充完整之后再请求
Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),
Rule(LinkExtractor(allow=r'/web/site0/tab5240/module14430/page\d+\.htm'), follow=True),
)
# parse函数有特殊功能,parse函数在父类里面有定义,crawlspider中不能定义parse函数,否则会重写父类方法
def parse_item(self, response):
item = {}
item["title"] = re.findall(r"<!--TitleStart-->(.*?)<!--TitleEnd-->", response.body.decode())[0]
item["publish_date"] = re.findall(r"发布时间:(.*?) ", response.body.decode())[0]
print(item)
# CrawlSpider后面可以继续构造请求 和 spider一样的用法
# yield scrapy.Request(
# url,
# callback=self.parse_detail,
# meta={"item": item}
# )
#
# def parse_detail(self, response):
# pass
CrawlSpider版本注意点:
- parse函数有特殊功能,parse函数在父类里面有定义,crawlspider中不能定义parse函数,否则会重写父类方法
- LinkExtractor 链接提取器,提取url地址,提取到的url地址交给parse函数发送请求。
- LinkExtractor 有一个集合(集合是唯一的),在当前响应中提取到的链接会放进去,并进行判重操作,如果有,就不会再提取。
- callback 提取出来的url地址的response会交给callback处理 callback后面必须是字符串
- follow 当前url地址的响应能够重新进入rules(经过rules包含的每一个Rule)来提取url地址。follow和callback看情况而写
- 如果callback为None,follow默认设置为True,否则默认为False。 这种逻辑的原因:不需要callback解析的一般是翻页或者跳板链接,自然需要follow跟进。
- Rule之间不能传递参数 只有手动yield才能通过meta传参
- url地址不完整 crawlspider会自动补充完整之后再请求
- 如果多个Pule都满足某一个url,会从rules中选择第一个满足的进行操作
常见参数的补充(了解)