提醒一下,爬虫有风险,我在前几天用学校的ip做爬虫测试,导致人家服务器nginx报错,吓死人了,所以爬虫太快相当于Ddos攻击,要坐牢的!!
猫眼电影知道我们很多学生都是拿他做测试,他的反爬措施就是让我们手动拉滑块,防止我们太快,已经是非常良心的了,一般一个ip整站抓取,只要不是太快,一般可以完成,但是就是别快,快了就是给你封ip
然后我继续提醒一下:我对爬虫的运行方式已经非常的清楚写的了,这个是我写的总结性笔记
#创建爬虫项目 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 爬虫文件名 爬虫目标网址(根网址) scrapy genspider maoyan maoyan.com2.明确需要抓取什么信息
- 电影名称
- 主演
- 时间
我需要这三个信息,我就是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)#把url一次性传到调度器,让调度器传给下载器 #yield方法相当于return ,但是又有点像next, 返回再继续,返回再继续,直到什么都没了 #callback非常重要,他代表了下载器请求完数据需要到那个解析进行处理(在maoyan.py中的parse)
然后咱们之前有写了一个items文件,即确定要提取的字段,把他引入到爬虫文件中
#引入items from ..items import MaoyanItem #怎么使用呢? """ item = MaoyanItem() #然后咱们不是有三个数据需要抓取的 分别为 item['name'] = 解析以后的数据 item['star'] = 解析以后的数据 item['time'] = 解析以后的数据 yield item #提交上去给管道 """
完整代码如下:(在这里是spider文件夹下的maoyan.py)
# -*- coding: utf-8 -*- import scrapy from ..items import MaoyanItem class MaoyanSpider(scrapy.Spider): name = 'maoyan' allowed_domains = ['maoyan.com'] # 1.去掉start_urls # 2.重写start_requests() 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[@]/a/text()').get().strip() item['star'] = dd.xpath('.//p[@]/text()').get().strip() item['time'] = dd.xpath('.//p[@]/text()').get().strip() print(item) # 交给项目管道处理 yield item4.管道文件(数据保存的地方)** 新的方法记得去注册哦! **
在这个时候传给管道的文件就已经是非常完美了
大概这个时候数据是这个样子的
{'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(不过要注意编码,一行就能解决,但是我就不说,自己百度)
# -*- coding: utf-8 -*- # 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 class MaoyanPipeline(object): def process_item(self, item, spider): print(item) #{'name': '网络谜踪', 'star': '主演:约翰·赵,米切尔·拉,黛博拉·梅辛', 'time': '上映时间:2018-12-14'} return item #return item非常重要,必须写
So·····
接下来要做的:我现在的想法是把scrapy自带的MaoyanPipeline方法留着,自己写三个,分别存在csv文件、json文件和Mysql数据库
为了能够解释清楚:管道的基本用法:
class SomethingPipeline(object): def __init__(self): # 可选实现,做参数初始化等 # 就是初始化,就是相当于王者荣耀开局的200金币,后面就不会在有这种待遇,想要有这个待遇就是开下一局 def process_item(self, item, spider): # item (Item 对象) – 爬取数据的item # spider (Spider 对象) – 爬取该item的spider # 这个方法必须实现,每个item pipeline组件都需要调用该方法, # 这个方法必须返回一个 Item 对象,被丢弃的item将不会被之后的pipeline组件所处理。 return item def open_spider(self, spider): # spider – 被开启的spider # 可选,spider开启时,这个方法被调用。 def close_spider(self, spider): # spider – 被关闭的spider # 可选,spider关闭时,这个方法被调用1.csv文件
重要!重要!重要!
写完代码以后要先去settings.py文件中进行管道注册
写完代码以后要先去settings.py文件中进行管道注册
写完代码以后要先去settings.py文件中进行管道注册
!!否则无法使用!!
#相当于有了驾照才能上路,scrapy也要在settings里面进行注册,才能让我们写的方法合法运行 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): # csv文件的位置,无需事先创建 store_file = os.path.dirname(__file__) + '/CSV/maoyan.csv' # 打开(创建)文件 self.file = open(store_file, 'w',newline='',encoding='utf-8') # csv写法 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:pass3.爬虫结束关闭文件
def close_spider(self,spider): self.file.close()4.一个保存csv文件保存完整代码
class Maoyan_csv_Pipeline(object): def __init__(self): # csv文件的位置,无需事先创建 store_file = os.path.dirname(__file__) + '/CSV/maoyan.csv' # 打开(创建)文件 self.file = open(store_file, 'w',newline='',encoding='utf-8') # csv写法 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()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)