环境:

1.windows 10
2.Python 3.7
3.Scrapy 1.7.3
4.mysql 5.5.53

一、Scrapy 安装

1. Scrapy:是一套基于Twisted的一部处理框架,是纯Python实现的爬虫框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容或者各种图片。
1. 安装命令:pip install scrapy
2. 查看是否安装成功,命令: scrapy

二、项目实战

1. 抓取豆瓣电影('https://movie.douban.com/top250')Top250数据,并将数据保存为csv,json和存储到数据库中
2. 一个完整项目基本包括:新建项目、明确目标、制作爬虫、存储内容四个步骤。

(一)、新建项目

1. 创建项目
命令: scrapy startproject [项目名称] 例:scrapy startproject Douban
项目目录结构:
# Douban
# Douban
# spiders
# __init__.py
# __init__.py
# items.py
# middlewares.py
# pipelines.py
# settings.py
# scrapy.cfg
2.创建爬虫
在spiders下执行命令: scrapy genspider [爬虫名] [待爬取网站的域名] 例:scrapy genspider douban_top250 movie.douban.com (此时spiders目录下会生成一个'douban_top250.py'爬虫文件)

== 注意:爬虫名称不能与项目名称重复 ==

(二)、明确目标


1. 明确要抓取哪些数据,并在 items.py 文件中进行定义.

   例:
import scrapy class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field() # 序号
serial_num = scrapy.Field()
# 电影名称
movie_name = scrapy.Field()
# 电影介绍
introduce = scrapy.Field()
# 电影评论数
evaluate_num = scrapy.Field()
# 电影描述
describe = scrapy.Field()
# 电影星级
star = scrapy.Field()

(三)、制作爬虫

1.打开爬虫文件(douban_top250.py)

    # -*- coding: utf-8 -*-
import scrapy class DoubanTop250Spider(scrapy.Spider):
# 爬虫名称
name = 'douban_top250'
# 允许的域名
allowed_domains = ['movie.douban.com']
# 入口URL
start_urls = ['https://movie.douban.com/top250'] def parse(self, response):
pass

2.在settings.py文件中开启 'USER_AGENT' 并设置为正确的代理

3.输出爬取的信息 例:

  def parse(self, response):
print(response.text)
4.执行爬虫运行命令: scrapy crawl [爬虫名称]   例: scrapy crawl douban_top250

== 注意:必须在 spiders 文件夹下执行 scrapy crawl 命令 ==

5.解析爬取的网页数据,例:
# -*- coding: utf-8 -*-
import scrapy
from Douban.items import DoubanItem
class DoubanTop250Spider(scrapy.Spider):
# 爬虫名称
name = 'douban_top250'
# 允许的域名
allowed_domains = ['movie.douban.com']
# 入口URL
start_urls = ['https://movie.douban.com/top250'] # 默认的解析方法
def parse(self, response):
# 导入item文件,实例对象
res = DoubanItem()
# 书写详细的xpath语句对数据进行解析
# 获取第一页的所有电影
movie_list = response.xpath('//div[@class="article"]/ol[@class="grid_view"]/li')
# 循环获得的电影
for movie in movie_list:
# 获取电影序号
res['serial_num'] = movie.xpath('.//div[@class="item"]/div[@class="pic"]/em/text()').extract_first()
# 获取电影名称
titles = movie.xpath('.//div[@class="item"]/div[@class="info"]/div[@class="hd"]/a/span/text()').extract()
movie_name = ''
for title in titles:
movie_name = movie_name + "".join(title.split())
res['movie_name'] = movie_name
# 获取电影介绍
res['introduce'] = "".join(movie.xpath('.//div[@class="bd"]/p/text()').extract_first().split())
# 获取电影评论数
res['evaluate_num'] = movie.xpath('.//div[@class="star"]/span[4]/text()').extract_first()
# 获取电影描述
res['describe'] = movie.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()').extract_first()
# 获取电影的评分
res['score'] = movie.xpath('.//div[@class="star"]/span[2]/text()').extract_first()
# 将结果提交至管道pipelines里面,进行数据的清洗以及存储
yield res
# 解析下一页规则
string = response.xpath('.//span[@class="next"]/a/@href').extract_first()
if string :
href = self.start_urls[0] + string
yield scrapy.Request(href,callback=self.parse)

(四)、存储内容


1、将数据保存为 json、csv 文件

   命令:scrapy crawl [爬虫名称] -o [保存文件名]
例:
1. scrapy crawl douban_top250 -o douban1.json
2. scrapy crawl douban_top250 -o douban2.csv

2、将数据保存至数据库中

  1. 创建mysql数据库及相关表
2. 在settings.py文件中开启 EXTENSIONS 设置
3. 在pipelines.py文件中导入pymysql模块
4. pipelines.py文件中类的命名是创建项目时自动生成的,一般为: [项目名称]Pipeline
5. 在类中process_item方法内进行保存数据操作
例:
# -*- 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 # 导入pymysql模块
import pymysql class DoubanPipeline(object): # 初始化相关属性
def __init__(self):
# 连接database
try:
self.conn = pymysql.connect(
host="127.0.0.1", # 数据库IP地址
port=3306, # 端口号
db="python_movie", # 数据库名称
user="root", # 用户名
password="root", # 密码
charset="utf8", # 编码格式
use_unicode=True, # 指定字符的编码、解码格式
cursorclass=pymysql.cursors.DictCursor, # 数据返回格式
)
# 得到一个可以执行SQL语句的光标对象
self.cursor = self.conn.cursor()
except Exception as e:
print(e) # 开启爬虫时执行,只执行一次
def open_spider(self,spider):
pass # 处理提取的数据(保存数据)
def process_item(self, item, spider):
sql = "INSERT INTO movie (serial,`name`,introduce,evaluate,`describe`,score) VALUES (%s,%s,%s,%s,%s,%s)"
# 执行sql语句
try:
self.cursor.execute(sql, tuple(item.values()))
self.conn.commit()
except Exception as e:
print(e) # 关闭爬虫时执行,只执行一次。 (如果爬虫中间发生异常导致崩溃,close_spider可能也不会执行)
def close_spider(self, spider):
self.cursor.close()
self.conn.close()

(五)、下载中间件编写


1. 设置代理 IP

1.在middlewares.py文件中编写
2.创建一个类,继承 object,在此类中编写代理IP
3.在类中创建方法
def process_request(self,request,spider):
pass
注意:这个方法名称是固定默认的,
4.在process_request方法中设置request中的meta属性中的prproxy参数,参数值为自己的代理服务器与端口号
request.meta['proxy'] = '[IP地址/域名]:[端口号 ]'
5.在process_request方法中设置代理的用户名与密码,固定格式为:
proxy_name_pass = '[用户名]:[密码]'
注意:用户名与密码中间用':'号分割
6.需要用base64.b64encode()对用户名与密码进行加密,而且base64.b64encode()只接受bytes格式的字符串,故:
proxy_name_pass = base64.b64encode(b'[用户名]:[密码]')
7.设置http请求头
request.headers['Proxy-Authorization'] = 'Basic ' + proxy_name_pass.decode()
8.将代理中间添加至settings.py中的 DOWNLOADER_MIDDLEWARES 中进行注册
例:
在 middlewares.py 中编写中间件
class my_proxy(object):
# 这个方法名 'process_request' 是固定的
def process_request(self,request,spider):
# 设置代理服务器IP地址
request.meta['proxy'] = "这里写代理IP:这里写端口号"
# 设置代理服务器账号与密码(注意账号与密码用 ':' 号分割,并且将字符串变为bytes格式)
proxy_name_pass = b"这里写账号:这里写密码"
# 加密账号与密码
encode_name_pass = base64.b64encode(proxy_name_pass)
# 设置代理服务请求头(注意:Basic后面必须加空格,而且加密后的账号与密码必须转为字符串格式才能拼接)
request.headers['Proxy-Authorization'] = 'Basic ' + encode_name_pass.decode()  
在 settings.py 中设置中间件
# 注意,后面的数字,表示中间件的优先级,多个中间价同时启用时优先级不可以相同
DOWNLOADER_MIDDLEWARES = {
'Douban.middlewares.DoubanDownloaderMiddleware': 543,
'Douban.middlewares.my_proxy': 544,
}

2. 设置 User-Agent

1.同上,在middlewares.py中创建一个类,在默认的process_request()方法中编写中间件
2.同上,将编写的中间件添加至settings.py中的 DOWNLOADER_MIDDLEWARES 中进行注册
3.具体操作直接上代码:
例:
在 middlewares.py 中编写中间件
# 设置代理IP中间件
class my_proxy(object):
def process_request(self,request,spider):
# 设置代理服务器IP地址
request.meta['proxy'] = "这里写代理IP:这里写端口号"
# 设置代理服务器账号与密码(注意账号与密码用 ':' 号分割,并且将字符串变为bytes格式)
proxy_name_pass = b"这里写账号:这里写密码"
# 加密账号与密码
encode_name_pass = base64.b64encode(proxy_name_pass)
# 设置代理服务请求头(注意:Basic后面必须加空格,而且加密后的账号与密码必须转为字符串格式才能拼接)
request.headers['Proxy-Authorization'] = 'Basic ' + encode_name_pass.decode() # 设置随机User_Agent中间件
class my_user_agent(object):
def process_request(self,request,spider):
# 在网络上搜索User_Agent列表
USER_AGENT_LIST = [
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]
# 随机获取一个user_agent,而random.choice()函数,表示从序列中随机选取一个元素
user_agent = random.choice(USER_AGENT_LIST)
# 设置Http请求头中的User_Agent
request.headers['User_Agent'] = user_agent
在 settings.py 中设置中间件
# 注意,后面的数字,表示中间件的优先级,多个中间价同时启用时优先级不可以相同
DOWNLOADER_MIDDLEWARES = {
'Douban.middlewares.DoubanDownloaderMiddleware': 543,
'Douban.middlewares.my_proxy': 544,
'Douban.middlewares.my_user_agent': 545,
}

== 注意:1. 中间件定义编写完成以后,一定要在 settings.py 文件中的 DOWNLOADER_MIDDLEWARES = {} 中注册中间件,表示启用此中间件;2. 爬虫文件名和爬虫名称不能相同,spider 目录内不能存在相同爬虫名称的项目文件 ==

交流群:887934385

Scrapy 框架 (学习笔记-1)的更多相关文章

  1. Scrapy框架学习笔记

    1.Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网 ...

  2. scrapy爬虫框架学习笔记(一)

    scrapy爬虫框架学习笔记(一) 1.安装scrapy pip install scrapy 2.新建工程: (1)打开命令行模式 (2)进入要新建工程的目录 (3)运行命令: scrapy sta ...

  3. phalcon(费尔康)框架学习笔记

    phalcon(费尔康)框架学习笔记 http://www.qixing318.com/article/phalcon-framework-to-study-notes.html 目录结构   pha ...

  4. Yii框架学习笔记(二)将html前端模板整合到框架中

    选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...

  5. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

  6. JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序

    前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...

  7. JavaSE中Map框架学习笔记

    前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...

  8. JavaSE中线程与并行API框架学习笔记1——线程是什么?

    前言:虽然工作了三年,但是几乎没有使用到多线程之类的内容.这其实是工作与学习的矛盾.我们在公司上班,很多时候都只是在处理业务代码,很少接触底层技术. 可是你不可能一辈子都写业务代码,而且跳槽之后新单位 ...

  9. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...

随机推荐

  1. C++学习笔记4_new和delete

    1. 默认的new和delete操作符new和delete是和c里面的mlloc和free是一样的,在堆中创建空间.堆中创建的,都要自己释放.C中void test(){ int *p=(int *) ...

  2. Android 常见内存泄露 & 解决方案

    前言 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃 (OOM) 等严重后果. 那什么情况下不能被 ...

  3. Kong01-Kong 介绍

    概述 Kong 是在客户端和(微)服务间转发API通信的API网关,通过插件扩展功能. Kong 的官方网站,https://konghq.com/kong Kong 的官方 Github 站点:ht ...

  4. [考试反思]1104csp-s模拟测试100: 终结

    这么好的整数场,就终结了我连续莫名考好的记录. 功德圆满了... 还是炸了啊.而且炸的还挺厉害(自己又上不去自己粘的榜单啦) 说实在的这场考试做的非常差劲.虽说分数不算特别低但是表现是真的特别差. T ...

  5. Redis过期--淘汰机制的解析和内存占用过高的解决方案

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! Red ...

  6. c#Func委托

    public delegate TResult Func<in T, out TResult>(T arg); 参数类型 T:此委托方法的参数类型 TResult:此委托方法的返回值类型 ...

  7. 图片转换成base64预览

    来源:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsDataURL 真心不错写得,思路比较清晰.已经测试过 注意: ...

  8. Arduino 基于 ESP8266 配置WIFI模块

    Arduino 基于 ESP8266 配置WIFI模块 使用ESP8266作为服务器,使用浏览器访问该服务器,从而控制LED灯 选择 [文件]->[示例]->[ESP8266WIFI]-& ...

  9. poj 1001 求高精度幂(Java, BigDecimal, pow, hasNext, stripTrailingZeros, toPlainString)

    求高精度幂 Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 180325   Accepted: 43460 Descripti ...

  10. 【SpringBoot | Swagger】SpringBoot整合Swagger

    SpringBoot整合Swagger 1. 什么是Swagger Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.简单说就是项目跑起来了, ...