CrawlSpider介绍
-
CrawlSpider是Scrapy框架中Spider爬⾍类的⼀个⼦类,除了继承到Spider的特性和功能外,还 有⾃⼰更加强⼤的规则爬取。
-
CrawlSpider是通过定义爬取的规则,爬⾍通过规则可以⾃动爬取数据。
• CrawlSpider适⽤于需要⾃动跟进链接并提取数据的场景。
• 普通的爬⾍项⽬可能需要⼿动编写代码来实现链接的提取和访问,并且更加灵活和⾃定义。
• 选择使⽤哪种⽅式取决于你的具体需求和个⼈偏好。
CrawlSpider创建
- 创建scrapy工程:scrapy startproject 项目名
- 创建爬虫文件:scrapy genspider -t crawl 项目名 www.xxx.com (跟之前创建文件的指令多了一个“-t crawl”,表示创建的爬虫文件是基于CrawlSpider这个类)
rules使用
rules就是CrawlSpider类独有的功能,rules是Rule对象的集合,用于匹配符合要求的目标网址;
参数介绍:Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)
- 参数1:指定连接提取器,设置提取链接的规则(正则表达式)
- 参数2:指定通过表达式解析到的链接的响应体返回函数(回调函数)
- 参数3:是否将链接提取器继续作用到链接提取器取出的链接网页中
follow
follow是一个布尔值(bool),指定了根据该规则从response提取的链接是否需要跟进。
如果为True,那么在请求到的响应体数据中,会继续搜索满足条件的链接再次请求,会一直深入解析页面直到没有新的匹配链接。
LinkExtractor(链接提取器)
LxmlLinkExtractor是用于提取链接的类,它提供了各种参数用于配置连接提取的行为。下面是各个参数的详细介绍:
-
allow:一个正则表达式(或正则表达式的列表),仅匹配的
URL会被提取 -
deny:一个正则表达式(或正则表达式的列表),匹配的
URL会被排除 -
allow_domains:一个字符串(或者字符串的列表),仅
提取这些域名下的链接 -
deny_domains:一个字符串(或者字符串的列表),
忽略这些域名下的链接 -
restrict_xpaths:一个XPATH表达式(或XPATH表达式的列表),仅在XPATH表达式匹配的区域内提取链接
-
restrict_css:一个CSS选择器(或选择器的列表),仅在CSS选择器匹配的区域内提取链接
-
restrict_text:一个正则表达式(或正则表达式的列表),仅提供文本符合正则表达式的链接
-
tags:一个字符串(或字符串的列表),提取指定标签下的链接,默认为(“a”,“area”)。
-
attrs:一个字符串(或字符串的列表),提取指定属性下的链接,默认为(“href”)。
-
canonicalize:如果为True,则对URL进行规范化处理(去除多余斜杠/统一大小写/规范编码)。
-
unique:如果为True,则仅提取唯一的链接(去除相同的链接)。
-
process_value:一个函数,用于处理提取的链接值。
-
deny_extensions:一个字符串(或字符串的列表),忽略匹配这些扩展名的链接。
-
strip:如果为True,则去除链接中的空白字符。
以上参数,可以灵活配置LxmlLinkExtractor,以适应不同的链接提取需求。
深度案例:(豆瓣)
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class DoubanSpider(CrawlSpider):
name = "douban"
allowed_domains = ["movie.douban.com"]
start_urls = ["https://movie.douban.com/top250"]
rules = (
# 翻页 ?这里会影响转译,所以需要换成\?来防止转译 但.不需要
Rule(LinkExtractor("https://movie.douban.com/top250?start=\d+&filter=$"), callback=None, follow=True),
# 详情页面获取,$是结尾的符号,follow=False 访问详情页面后,不再从详情页面中解析链接
Rule(LinkExtractor('https://movie.douban.com/subject/\d+/$'), callback="parse_item", follow=False),
)
def parse_item(self, response):
item = {"title":response.xpath('//h1/span[@property="v:itemreviewed"]/text()').get()}
print(item["title"])
return item
需要存储的话,pipelines.py需要编写一下,如下:
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
class DoubanTopPipeline:
def __init__(self):
self.file = open('douban.text','w+',encoding='utf-8')
def process_item(self, item, spider):
self.file.write(f'{item}\n')
return item
def close_spider(self):
self.file.close()
值得注意的是:这里爬取速度过快,可能会导致爬取数据不全的问题,可以通过更换代理id,cookies或者在setting.py里面设置一下爬取的速度(如下)等。
DOWNLOAD_DELAY = 0.5
Cookies设置
COOKIES_ENABLED:默认开启cookie,如果禁⽤,则不会发送任何cookie到Web服务器。
法1:在settings中设置cookie,在请求头中添加UA和cookie即可
DEFAULT_REQUEST_HEADERS = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'cookie': 'pgv_pvid=2232911505; pgv_info=ssid=s1787784160&pgvReferrer=; clientip=; paytoken=; '
}
**法2:通过中间件设置cookie,request.cookies=cookie_dict(需要将复制的cookie字符串转换成字典)
class CookieDownloaderMiddleware:
def process_request(self, request, spider):
cookie_str = 'pgv_pvid=2232911505;pgv_info=ssid=s1787784160&pgvReferrer=; clientip=; paytoken='
# 字典推导式
cookie_dict = {i.split('=')[0]: i.split('=')[1] for i in
cookie_str.split('; ')}
print(cookie_dict)
request.cookies = cookie_dict
**法3:重写start_requests⽅法携带上cookie发送请求,构造请求并且yield(需要cookie字符串转成字典)
# 将字符串的cookie变成字典类型的cookie
cookie_str = 'pgv_pvid=2232911505; pgv_info=ssid=s1787784160&pgvReferrer='
# 字典推导式
cookie_dict = {i.split('=')[0]: i.split('=')[1] for i in cookie_str.split('; ')}
def start_requests(self):
yield scrapy.Request(url=self.start_urls[0],
callback=self.parse,
cookies=self.cookie_dict
)
POST请求
def start_requests(self): #post请求
yield scrapy.FormRequest(
url=self.start_urls[0],
callback=self.parse,
formdata={}, # 携带请求头
)