这个也是在基于scrapy框架的基础上实现的,所以scrapy的基本使用命令也是需要遵从的
scrapy startproject 工程名 (XXPro:XXproject)
cd 工程名
这里不需要切换目录,在项目目录下即可。
www.xxx.com是要爬取的网站。
scrapy genspider 爬虫文件名 www.xxx.com
在pycharm中直接执行是不管用的,无效。应该再在终端中执行
scrapy crawl 爬虫文件名 # 执行的是爬虫文件
项目下有一个settings文件,里面的文件介绍如下:
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
#显示指定类型的日志信息 而不显示其他乱七八糟的
LOG_LEVEL = 'ERROR'
# 设置用户代理 浏览器类型
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
# 取消注释改行,意味着开启管道存储。
# 300表示优先级,数值越小优先级越高
ITEM_PIPELINES = {
"weiboPro.pipelines.WeiboproPipeline": 300,
}
1. 数据解析
2. 在item类中定义相关的属性
3. 将解析的数据封装存储到item类型的对象
4. 将item类型的对象提交给管道进行持久化存储的操作
5. 在管道类的process_item中要将其接受到的item对象中存储的数据进行持久化存储操作
6. 在配置文件中开启管道
这个并不是很难。主要是理清他的思路是什么。
在工程目录下的爬虫文件(这里是weibo.py)写好保证能够爬取到信息之后,主要是将管道文件写好(pipelines.py)。
按照上面的6步走:
即爬取数据的过程
# (weibo.py爬虫文件)
# 不使用数据库,只保存到本地
import scrapy
from weiboPro.items import WeiboproItem
# 导包失败:右键项目目录 => 将目标标记为 => 源代码根目录
# 爬取微博失败了,返回为空。改为爬取B站了。
# 爬取B站的视频的名称和作者
class WeiboSpider(scrapy.Spider):
name = "weibo"
# allowed_domains = ["weibo.com"]
start_urls = ["https://www.bilibili.com/"]
def parse(self, response):
author = []
title = []
div_list = response.xpath('//*[@id="i_cecream"]/div[2]/main/div[2]/div/div[1]/div')
print("数据长度为", len(div_list))
for div in div_list:
# xpath返回的是列表,但是列表元素一定是Selector类型的对象
# extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('.//div[@class="bili-video-card__info--right"]//a/span[@class="bili-video-card__info--author"]/text()').extract() # xpath要从上一层的xpath开始找,必须在最前面加个. !!
# 对列表调用extract后,将列表的每一个Selector对象中的data对应的字符串提取了出来
title=div.xpath('.//div[@class="bili-video-card__info--right"]/h3/a/text()').extract()
# author, title解析到的为list,将其转为str
# 将列表转为字符串: .join方法
author = ''.join(author)
title = ''.join(title)
print('当前抽取的author', author)
print('当前抽取的title', title)
print(len(author), len(title))
# 3,4两步都在循环内,所以是每执行一次循环将item对象提交给管道并存储到本地
# 3.将解析的数据封装存储到item类型的对象
item = WeiboproItem()
item['author'] = author
item['title'] = title
# 4. 将item类型的对象提交给管道进行持久化存储的操作
yield item
class WeiboproItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 在item类中定义相关的属性
author = scrapy.Field()
title = scrapy.Field()
3,4两步在1.中已经体现,具体代码为:
# 3.将解析的数据封装存储到item类型的对象
item = WeiboproItem()
item['author'] = author
item['title'] = title
# 4. 将item类型的对象提交给管道进行持久化存储的操作
yield item
在这里重写了父类的两个方法:open_spider()和close_spider()方法。
open_spider()方法在开始爬虫时被调用一次,close_spider()方法在爬虫结束时被调用一次。这样实现了yield多次时,只打开关闭一次文件。
process_item()是将得到的item对象中的数据保存到本地。
# pipelines.py 管道文件
class WeiboproPipeline:
fp = None
def open_spider(self, spider):
# 重写父类的方法,只在开始爬虫时被调用一次
print("开始爬虫")
self.fp = open('./B站.txt', 'w', encoding='utf-8')
def process_item(self, item, spider):
author = item['author']
title = item['title']
print("当前写入的是:" + author + ":" + title + "\n")
self.fp.write(author + ":" + title + "\n")
return item
def close_spider(self, spider):
# 重写父类的方法,在爬虫结束时被调用一次
print("结束爬虫")
self.fp.close()
打开项目weiboPro路径下的settings.py文件,将ITEM_PIPELINES字典取消注释,即可开启管道。
ITEM_PIPELINES = {
"weiboPro.pipelines.WeiboproPipeline": 300,
}
运行结束之后,会在本地生成B站.txt文件,其中包含爬取的author和title
这里需要安装mysql,我还另外安装了navicat。安装好mysql之后,要新建连接,按照步骤操作即可。
这里需要mysql库。这个库是用来对数据库进行远程连接的,所以必须要有打开的数据库,打开的表才可以。
建立好之后,再按照上面的6步按部就班来就可以。
这里的管道文件中的每一个管道类(如持久化存储1的WeiboproPipeline
)对应将一组数据存储到一个平台或者载体中。上面的是保存到本地,所以我们还需要将再写一个类来将数据持久化存储到数据库中。
我也有好多东西不理解为什么要这么写
# 管道文件中一个管道类对应将一组数据存储到一个平台或者载体中
class mysqlPileLine:
# 每写一个管道类要将这个类写到settings.py的ITEM_PIPELINES中。
connect = None
cursor = None
def open_spider(self, spider):
# 重写父类的方法,在爬虫开始时调用一次
# 创建连接:pymysql.Connect
self.connect = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='liu1457154996', db='bzhan', charset='utf8') # db表示数据库的名称,我上面创建的数据库名称叫bzhan,即上图中的绿色圆柱
def process_item(self, item, spider):
# 创建游标
self.cursor = self.connect.cursor()
try:
self.cursor.execute('INSERT INTO bzhan (author, title) VALUES ("%s", "%s")' % (item['author'], item['title'])) # 这里的bzhan是bzhan数据库下的表的名称
self.connect.commit()
print("成功写入数据库", item['author'], item['title'])
except Exception as e:
print(e)
self.connect.rollback()
return item
def close_item(self, spider):
self.cursor.close() # 关闭游标
self.connect.close() # 关闭连接
在上面的基础上开启mysqlPileLine管道。
ITEM_PIPELINES = {
"weiboPro.pipelines.WeiboproPipeline": 300,
"weiboPro.pipelines.mysqlPileLine": 301,
}
在终端中输入scrapy crwal weibo后,得到数据库中的结果如下: