学习记录:
一、新建scrapy项目
- scrapy下载
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn Scrapy
- 在指定的文件路径下建立项目
scrapy startproject 项目名
如下:
- 新建spiders爬虫文件
scrapy genspider 文件名 所爬网页域名
注意:我们在创建文件的时候,要进入到其spiders目录下进行。我之前是直接复制它提示的指令去创建,后面却出现问题了。半天都没解决,其报错如下:
创建文件:
在pycharm中查看:
对于scrapy的详解: scrapy文档
二、豆瓣电影实战
豆瓣TOP250是一个练手学习的好地方。。。
整体框架:一个scrapy有很多个文件,我们只需编写我们需要的代码文件即可,其他不动它就可
- 网页解析数据
- douban .py
import scrapy
from scrapy.http import Request
from douban01.items import Douban01Item # 这个目前还没找到解决办法,只有这样用
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['movie.douban.com']
# start_urls = ['http://movie.douban.com/']
# 分页操作
def start_requests(self):
for page in range(10):
yield Request(url=f'https://movie.douban.com/top250?start={page * 25}&filter=')
# **kwargs 可以消除警告
def parse(self, response, **kwargs): # **kwargs消除警告
li_list = response.xpath('//ol[@class="grid_view"]/li')
for i in li_list:
actor = i.xpath('string(./div/div[2]/div[2]/p/text())')[0].extract().strip()
detail = i.xpath('./div/div[2]/div[2]/p/text()')[1].extract().strip()
rank = i.xpath('string(./div/div[2]/div[2]/div/span[2]/text())')[0].extract()
title = i.xpath('./div/div[2]/div/a/span[1]/text()')[0].extract()
move = Douban01Item(actor=actor, detail=detail, rank=rank, title=title)
# print(title)
yield move
scrapy对于多页请求,它专门有个方法:start_requests Scrapy 中的起始请求 通过start_requests 函数实现
# 分页操作
def start_requests(self):
for page in range(10):
yield Request(url=f'https://movie.douban.com/top250?start={page * 25}&filter=')
爬虫的主要目标是从页面爬取非结构性的数据然后提取出结构性数据。Scrapy提供Item类可以实现这样的要求。Item对象是简单的容器,用于保存爬取到的数据。
items.py
item 类实例化,后面可传递到管道进行数据处理
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class Douban01Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
actor = scrapy.Field()
detail = scrapy.Field()
rank = scrapy.Field()
title = scrapy.Field()
settings.py
- 在 settings.py 中设置启用管道,找到 ITEM_PIPELINES
- 设置请求头
- 关掉君子协议,找到它把他注释即可
- 并发数可以直接设置,默认数值16
BOT_NAME = 'douban01'
SPIDER_MODULES = ['douban01.spiders']
NEWSPIDER_MODULE = 'douban01.spiders'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36'
ITEM_PIPELINES = {
'douban01.pipelines.Douban01Pipeline': 300, # 管道优先级,数字越小越先执行
}
2.1、存储在CSV
pipelines.py
爬取获得的数据通过item 类实例化,然后传递到管道,通过管道进行进一步处理。在这里我们可以设置数据存储方式或位置。
如果要存储数据在CSV或json形式的话,我们可以不用设置管道文件,可以直接给命令达到效果。
- CSV
- 终端运行命令:scrapy crawl douban -o 豆瓣.csv
- 注意是要到其spiders目录下执行
- JSON
- 终端运行命令:scrapy crawl douban -o 豆瓣.json
- 直接这样运行最后数据会乱码的
如图:
- 我们可以指定编码格式, 即在命令后面增加 -s FEED_EXPORT_ENCODING=utf-8 如下
scrapy crawl douban -o 豆瓣.json -s FEED_EXPORT_ENCODING=utf-8
2.2、存储在Excel
其他不变,只是编写pipelines.py即可:
import openpyxl # 写入 Excel 表中
class Douban01Pipeline:
def __init__(self):
self.wb = openpyxl.Workbook() # 创建工作薄
self.ws = self.wb.active # 建表
self.ws.title = '豆瓣TOP250'
self.ws.append(("影片名", "评分", "剧情", "演员"))
def close_spider(self, spider):
self.wb.save("豆瓣电影数据.xlsx")
def process_item(self, item, spider):
actor = item.get('actor')
detail = item.get('detail')
rank = item.get('rank')
title = item.get('title')
self.ws.append((title, rank, detail, actor))
return item
效果:Excel中打开
2.3、存储在数据库—sql server
sql server中建表:
create table douban
(
id int identity(1, 1) not null primary key, --identity(1, 1) 起始值1,自增量1,且设置ID为主键
影片名 varchar(30) not null,
评分 varchar(10) not null,
剧情 varchar(80) not null,
演员 varchar(100) not null
)
编写pipelines.py
- 批量写入数据库
import pymssql # 引入pymssql模块
class Douban03Pipeline:
def __init__(self):
self.connect = pymssql.connect(server='LAPTOP-DUHL1TTU\YXHLHM', # 服务器名或本地IP
user='sa', # 账户
password='123456', # 自己设置的密码
database='yxh2') # 你要连接的数据库名
self.cursor = self.connect.cursor()
self.data = [] # 准备一个空列表作为容器
def close_spider(self, spider):
# 在最后关闭时,如还有数据则全部写入
if len(self.data) > 0:
self.to_sql()
self.connect.commit() # 提交数据
self.connect.close() # 关闭
def process_item(self, item, spider):
# item中取出数据
actor = item.get("actor")
detail = item.get("detail")
rank = item.get("rank")
title = item.get("title")
a = (title, rank, detail, actor)
self.data.append(a)
# 列表数据达到100条时进行写入
if len(self.data) == 20:
self.to_sql()
self.connect.commit()
self.data.clear() # 每写入100条后,就清除列表里的数据,避免重复
return item
def to_sql(self):
sql = "insert into douban(影片名,评分,剧情,演员) values(%s,%s,%s,%s)"
self.cursor.executemany(sql, self.data)
self.connect.commit()
数据库中查看:
学习中~~