爬虫scrapy总结笔记
1.声明一下:
提醒一下,爬虫有风险,我在前几天用学校的ip做爬虫测试,导致人家服务器nginx报错,吓死人了,所以爬虫太快相当于Ddos攻击,要坐牢的!! 猫眼电影知道我们很多学生都是拿他做测试,他的反爬措施就是让我们手动拉滑块,防止我们太快,已经是非常良心的了,一般一个ip整站抓取,只要不是太快,一般可以完成,但是就是别快,快了就是给你封ip 然后我继续提醒一下:我对爬虫的运行方式已经非常的清楚写的了,这个是我写的总结性笔记
1.创建项目
scrapy startproject Maoyan
cd Maoyan
scrapy genspider maoyan maoyan.com
Scrapy基本组件
- 引擎(Engine)----------整个框架核心
- 爬虫程序(Spider)------数据解析提取
- 调度器(Scheduler)-----维护请求队列
- 下载器(Downloader)----获取响应对象
- 管道文件(Pipeline)-----数据入库处理
scrapy项目目录结构
Maoyan
├── maoyan
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│ ├── maoyan.py
└── scrapy.cfg
2.创建项目的基本步骤
【1】新建项目和爬虫文件
scrapy startproject 项目名
cd 项目文件夹
新建爬虫文件 :scrapy genspider 文件名 域名
【2】明确目标(items.py)
【3】写爬虫程序(文件名.py)
【4】管道文件(pipelines.py)
【5】全局配置(settings.py)
【6】运行爬虫
1) 终端: scrapy crawl 爬虫名
2) pycharm运行
a> 创建run.py(和scrapy.cfg文件同目录)
from scrapy import cmdline
cmdline.execute('scrapy crawl maoyan'.split())
b> 直接运行 run.py 即可
3.创建项目的基本步骤实现
tips:这个只是get请求的项目
1.新建项目和爬虫文件
scrapy startproject Maoyan
cd Maoyan
scrapy genspider maoyan maoyan.com
2.明确需要抓取什么信息
我需要这三个信息,我就是scrapy项目中的items文件中写入三个
"""items.py"""
import scrapy
class MaoyanItem(scrapy.Item):
name = scrapy.Field()
star = scrapy.Field()
time = scrapy.Field()
3.写爬虫程序(位于spider文件下的maoyan.py)
在这里有一个重点
因为猫眼是通过url的offset=页数,然而scrapy给的start_url有一个很大的局限性,所以我就打算重新写一个方法代替start_url
start_url:就是在程序第一次启动的时候,去请求的链接,一个链接就请求一次,如果有成千上万条请求那不就GG了
猫眼电影翻页逻辑
https://maoyan.com/board/4?offset=0
https://maoyan.com/board/4?offset=10
····
https://maoyan.com/board/4?offset=90
所以重新写一个方法,代替start_url
方法如下:
def start_requests(self):
for page in range( 0, 91, 10):
url = f'https://maoyan.com/board/4?offset={page}'
yield scrapy.Request(url=url,callback=self.parse)
然后咱们之前有写了一个items文件,即确定要提取的字段,把他引入到爬虫文件中
from ..items import MaoyanItem
"""
item = MaoyanItem()
#然后咱们不是有三个数据需要抓取的
分别为
item['name'] = 解析以后的数据
item['star'] = 解析以后的数据
item['time'] = 解析以后的数据
yield item
#提交上去给管道
"""
完整代码如下:(在这里是spider文件夹下的maoyan.py)
import scrapy
from ..items import MaoyanItem
class MaoyanSpider(scrapy.Spider):
name = 'maoyan'
allowed_domains = ['maoyan.com']
def start_requests(self):
for offset in range(0, 91, 10):
url = 'https://maoyan.com/board/4?offset={}'.format(offset)
yield scrapy.Request(url=url, callback=self.parse_html)
def parse_html(self, response):
dd_list = response.xpath('//dl/dd')
for dd in dd_list:
item = MaoyanItem()
item['name'] = dd.xpath('.//p[@class="name"]/a/text()').get().strip()
item['star'] = dd.xpath('.//p[@class="star"]/text()').get().strip()
item['time'] = dd.xpath('.//p[@class="releasetime"]/text()').get().strip()
print(item)
yield item
4.管道文件(数据保存的地方)** 新的方法记得去注册哦! **
在这个时候传给管道的文件就已经是非常完美了
大概这个时候数据是这个样子的
{'name':'喜羊羊与灰太狼','star':'未知','time':'2000年'}
·······
{'name':'XXXXXX','star':'XX','time':'XXX'}
然后就是开始数据持久化
按照比赛要求,数据的格式为:
1.csv
2.json
3.Mysql
由于csv和json都是有固定格式的,scrapy所以就帮我们封装好了,but,我们必须自己手写一个方法
首先一进到管道文件的样子是:方法的最后面必须加上 return item 这个非常重要
现在只要在爬虫名后面添加 -o 文件名.csv
或者 -o 文件名.json(json因为默认不输出utf-8),如果不设置编码会乱码,具体怎么做,我就不想写了,因为百度可以百度到,可以这么写,scrapy输出json乱码
如果你要拿csv(因为scrapy封装,但是有一个很大的问题,就是顺序)
我之前的顺序是,name,star,time,如果只是有scrapy的方法,他不会按照你的顺序,所以我直接写了一个方法
from scrapy import cmdline
cmdline.execute('scrapy crawl maoyan -o maoyan.csv'.split())
要拿json的话,就去把maoyan.csv改成maoyan.json(不过要注意编码,一行就能解决,但是我就不说,自己百度)
class MaoyanPipeline(object):
def process_item(self, item, spider):
print(item)
return item
So·····
接下来要做的:我现在的想法是把scrapy自带的MaoyanPipeline方法留着,自己写三个,分别存在csv文件、json文件和Mysql数据库
为了能够解释清楚:管道的基本用法:
class SomethingPipeline(object):
def __init__(self):
def process_item(self, item, spider):
return item
def open_spider(self, spider):
def close_spider(self, spider):
1.csv文件
重要!重要!重要!
写完代码以后要先去settings.py文件中进行管道注册
写完代码以后要先去settings.py文件中进行管道注册
写完代码以后要先去settings.py文件中进行管道注册
!!否则无法使用!!
ITEM_PIPELINES = {
'Maoyan.pipelines.MaoyanPipeline': 300,
'Maoyan.pipelines.Maoyan_csv_Pipeline':299,
'Maoyan.pipelines.Maoyan_json_Pipeline':269,
'Maoyan.pipelines.Maoyan_Mysql_Pipline':209,
}
思路:
1.先初始化,然后在初始化写入表头
def __init__(self):
store_file = os.path.dirname(__file__) + '/CSV/maoyan.csv'
self.file = open(store_file, 'w',newline='',encoding='utf-8')
self.writer = csv.writer(self.file)
self.writer.writerow(['电影名字','电影主演','电影上映时间'])
2.然后插入数据
def process_item(self, item, spider):
if item['name']:
self.writer.writerow([item['name'],item['star'],item['time']])
return item
else:pass
3.爬虫结束关闭文件
def close_spider(self,spider):
self.file.close()
4.一个保存csv文件保存完整代码
class Maoyan_csv_Pipeline(object):
def __init__(self):
store_file = os.path.dirname(__file__) + '/CSV/maoyan.csv'
self.file = open(store_file, 'w',newline='',encoding='utf-8')
self.writer = csv.writer(self.file)
self.writer.writerow(['电影名字','电影主演','电影上映时间'])
def process_item(self, item, spider):
if item['name']:
self.writer.writerow([item['name'],item['star'],item['time']])
return item
else:pass
def close_spider(self,spider):
self.file.close()
来一个截图,嘿嘿,不过提醒一下,编码问题 虽然简单,但是很重要哦
? 简单在于,网页是什么编码我们就是什么编码
? 重要在于,你不写就会乱码(一堆符号,看不懂 =呜呜呜=)
2.json文件
首先先看看json的基本格式:
{ "people": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }
]}
3.Mysql数据库
完整代码如下:
class Maoyan_Mysql_Pipline:
def open_spider(self,spider):
self.db = pymysql.connect(host='localhost',user='xiaochen',port=3306,password='123456',db='Maoyan',charset='utf8mb4')
self.cur = self.db.cursor()
self.ins = 'insert into tb_maoyan values (%s,%s,%s)'
def process_item(self, item, spider):
li = [
item['name'],
item['star'],
item['time']
]
self.cur.execute(self.ins,li)
self.db.commit()
time.sleep(0.1)
return item
def close_spider(self,spider):
self.cur.close()
self.db.close()
|