关于CrawlSpider
CrawlSpider 是Scrapy框架中的一个爬虫类,用于快速开发和部署基于规则的爬虫。
CrawlSpider 继承自Scrapy的Spider类,但与普通的Spider类不同,CrawlSpider可以根据一些规则自动发现和跟踪链接,从而实现深度爬取。
CrawlSpider的特点包括:
-
自动跟踪链接:CrawlSpider可以根据指定的规则自动发现和跟踪链接,无需手动定义start_requests()方法。
-
规则定义:CrawlSpider使用rules属性来定义规则,规则可以包括允许和禁止的URL模式、回调函数等。
-
多层爬取:CrawlSpider可以实现多层级的爬取,通过设置规则的深度限制,可以控制爬取的层级。
-
提取链接和数据:CrawlSpider可以通过LinkExtractor提取链接,并自动调用指定的回调函数处理提取到的数据。
使用CrawlSpider可以很方便地实现爬虫的配置和开发,提高爬取效率和准确性。
CrawlSpider创建
要创建crawlspider,首先需要安装Scrapy。以下是crawlspider的安装教程:
-
确保已安装Python和pip。
-
打开命令提示符或终端。
-
使用以下命令安装Scrapy:
pip install scrapy
-
安装完成后,可以使用以下命令检查是否安装成功:
scrapy version
如果成功安装,会显示Scrapy的版本号。
-
创建新的Scrapy项目。在命令提示符或终端中,使用以下命令创建一个名为"myproject"的新项目:
scrapy startproject myproject
这将在当前目录下创建一个名为"myproject"的文件夹,并且包含一个默认的Scrapy项目结构。
-
进入新创建的项目目录:
cd myproject
-
创建一个新的crawlspider:
scrapy genspider -t crwal myspider example.com
这将在项目中创建一个名为"myspider"的crawlspider,以"example.com"作为起始URL。
-
CrawlSpider是Scrapy框架中的一个类,它提供了一种更便捷的方式来构建一个可以爬取多个网站的爬虫。
import scrapy from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor class MySpider(CrawlSpider): name = 'example' allowed_domains = ['example.com'] start_urls = ['http://www.example.com']
接下来,定义规则(Rule)来指定爬取的链接和对应的处理方法。规则是一个Rule对象的列表,每个规则都包含一个LinkExtractor和一个callback函数。
rules = ( Rule( LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', )), callback='parse_category', follow=True ), )
在这个例子中,用LinkExtractor来定义某个链接的匹配规则,其中allow表示允许的链接pattern,deny表示不允许的链接pattern。callback指定了对应链接的处理函数。follow=True表示是否继续跟进从这个链接提取到的链接。
最后,在Spider中实现处理函数。
def parse_category(self, response): self.logger.info('Visited %s', response.url) # 在这里处理response,如提取信息、存储数据等
在这个例子中,parse_category函数用于处理符合规则的链接,可以在这个函数中提取需要的信息,存储数据等。
最后,在命令行中运行爬虫:
scrapy crawl example
以上就是使用CrawlSpider的基本教程。通过使用CrawlSpider,你可以更便捷地构建一个可以爬取多个网站的爬虫,并且通过定义规则来指定爬取的链接和对应的处理方法。
具体应用
使用其框架,对每个页面中的每个新闻问政标题里边的详细内容进行多层爬取
首先start_url列表中填入所爬取的网址,在LinkExtrator中,写入一段正则表达式,表达式根据分页url规律所编写
class SixSpider(CrawlSpider):
name = "six"
# allowed_domains = ["www.baidu.com"]
start_urls = ["https://wz.sun0769.com/political/index/politicsNewest?id=1&page=1"]
# 链接提取器,allow=“正则表达式”
# 作用:根据指定的规则进行指定链接的提取
link=LinkExtractor(allow=r"id=1&page=\d+")
rules = (
# 规则解析器
# 作用:根据链接提取器提取的的链接按照指定的规则去进行解析操作
Rule(link, callback="parse_item", follow=False),
# follow=false是进行局部的链接提取
# follow=true则将链接提取器 继续作用到 链接提取器提取的链接 所对应的页面
)
这边的follow选项我建议学习测试的话,建议选择False,进行一个分页的局部爬取,开启True的话,会把每个分页的所有内容进行爬取,这会触发网站对其的爬虫检测,封锁IP了,一开始就不建议开启了
# 解析新闻标题
def parse_item(self, response):
tr_list=response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
for tr in tr_list:
new_title=tr.xpath('./span[3]/a/text()').extract_first()
print(new_title)
new_url=tr.xpath('./span[3]/a/@href').extract_first()
new_url="https://wz.sun0769.com"+str(new_url)
item=SixbloodItem()
item['new_title']=new_title
yield scrapy.Request(url=new_url,callback=self.parse_detail,meta={'item':item},dont_filter=True)
在回调方法中,就可以对于当前分页的标题和其详情页的URL进行爬取,创建一个item对象,将爬取的值储存到其中,在通过请求传参,实现多层爬取,其实也能将详情页的URL放入链接提取器中,此次案例就不再使用了
# 解析新闻内容
def parse_detail(self, response):
# extract():这个方法返回的是一个数组list,,里面包含了多个string,如果只有一个string,则返回['ABC']这样的形式。
# extract_first():这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
new_detail=response.xpath('/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()').extract()
# 将列表内容转换为字符串
new_detail=" ".join(new_detail)
# 消除里边的空格和换行符
new_detail=new_detail.replace('\n', '').replace('\r', '')
# 储存到item中去
item=response.meta['item']
item['new_detail']=new_detail
# 最终将所有response存储到item中,由item提交到管道类中去
yield item
在管道类中进行持久化的储存
from itemadapter import ItemAdapter
class SixbloodPipeline:
fp = None
# 对爬取的数据进行储存
# 重写一个父类的方法:该方法只会在开始爬虫的时候执行一次
def open_spider(self, spider):
print("开始爬虫》》》》")
# 保存在当前文件WyNews.txt中
self.fp = open('./CzNet.txt', 'w', encoding='utf-8')
def process_item(self, item, spider):
new_title = item['new_title']
new_detail = item['new_detail']
print(new_title)
self.fp.write(new_title + ':' + new_detail + '\n')
# 传递给下一个即将被执行的管道类
return item
def close_spider(self, spider):
print("结束爬虫》》》》")
self.fp.close()
打开管道类
爬取前的Setting.py文件基本设置
ROBOTSTXT_OBEY = False
LOG_LEVEL='ERROR'
USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0"
item.py文件设置
import scrapy
class SixbloodItem(scrapy.Item):
new_title=scrapy.Field()
new_detail=scrapy.Field()
pass
运行文件全部完整代码
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from sixBlood.items import SixbloodItem
class SixSpider(CrawlSpider):
name = "six"
# allowed_domains = ["www.baidu.com"]
start_urls = ["https://wz.sun0769.com/political/index/politicsNewest?id=1&page=1"]
# 链接提取器,allow=“正则表达式”
# 作用:根据指定的规则进行指定链接的提取
link=LinkExtractor(allow=r"id=1&page=\d+")
rules = (
# 规则解析器
# 作用:根据链接提取器提取的的链接按照指定的规则去进行解析操作
Rule(link, callback="parse_item", follow=True),
# follow=false是进行局部的链接提取
# follow=true则将链接提取器 继续作用到 链接提取器提取的链接 所对应的页面
)
# 解析新闻标题
def parse_item(self, response):
tr_list=response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
for tr in tr_list:
new_title=tr.xpath('./span[3]/a/text()').extract_first()
print(new_title)
new_url=tr.xpath('./span[3]/a/@href').extract_first()
new_url="https://wz.sun0769.com"+str(new_url)
item=SixbloodItem()
item['new_title']=new_title
yield scrapy.Request(url=new_url,callback=self.parse_detail,meta={'item':item},dont_filter=True)
# 解析新闻内容
def parse_detail(self, response):
# extract():这个方法返回的是一个数组list,,里面包含了多个string,如果只有一个string,则返回['ABC']这样的形式。
# extract_first():这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
new_detail=response.xpath('/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()').extract()
# 将列表内容转换为字符串
new_detail=" ".join(new_detail)
# 消除里边的空格和换行符
new_detail=new_detail.replace('\n', '').replace('\r', '')
# 储存到item中去
item=response.meta['item']
item['new_detail']=new_detail
# 最终将所有response存储到item中,由item提交到管道类中去
yield item
最终项目的命令行输入scrapy crawl 项目名,完成爬取