Scrapy是什么?
Scrapy是一个由Python编写的开源协作爬虫框架,可以快速的从网站中提取需要的数据。Scrapy基础爬虫部分内部已经实现,只需编写采集规则即可,简单易用,扩展性强,多平台运行兼容性好。
详细笔者不做介绍,dddd(懂的都懂 哈哈)
scrapy官网: https://scrapy.org/
github地址:https://github.com/scrapy/scrapy
一、Scrapy安装
1.安装 lxml:pip3 install lxml。
2.安装pyOpenSSL:在官网下载wheel文件。
3.安装Twisted:在官网下载wheel文件。
4.安装PyWin32:在官网下载wheel文件
5.最后安装 scrapy,pip3 install scrapy
注意: 2、3、4如果采用pip3在线安装失败 可以采用下载后 pip install +文件路径/文件名进行安装
下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
二、Scrapy基本使用
- scrapy 创建项目
scrapy startproject projecname
得到一下目录
└─projecname
│ scrapy.cfg #开发配置文件
│
└─projecname #工程模块
│ items.py #获取定义模块 定义使用的字段
│ middlewares.py #中间件 定义中间件
│ pipelines.py #处理数据
│ settings.py #工程设置文件
│ __init__.py #空文件
│
├─spiders #爬虫目录,用于放置各种爬虫类文件
│ │ __init__.py #空文件
- 新建一个爬虫
在spiders文件夹下创建demo.py
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demo'
start_urls = ['https://www.baidu.com']
def parse(self, response):
# 爬取百度首页热点和连接
for hot in response.css("li.hotsearch-item"):
title = hot.css(".title-content-title::text").get()
href = hot.css("a::attr('href')").get()
item = {'title': title,'href':href}
print(item)
yield item
pass
- 运行爬虫
scrapy crawl demo
一个简单的demo就完成了
三、Scrapy基本介绍
官网给出的数据流图和解释
Scrapy 中的数据流由执行引擎控制,如下所示:
- 引擎获取最初的请求进行爬行。
- 引擎将请求发送至调度器。
- 调度器调度将请求发送引擎。
- 引擎将请求通过下载器中间件发送到下载器。
- 页面完成下载后, 下载器生成一个响应(带有该页面)通过下载器中间件将其发送到引擎。
- 该引擎接收来自响应,下载器将其发送到爬虫进行处理,其中通过爬虫中间件。
- 爬虫处理响应并返回项目和新的请求。
- 引擎发送处理好的数据,然后把处理的请求的调度,并请求下一个可能的爬虫请求。
- 该过程重复(从第 1 步开始),直到不再有来自Scheduler 的请求。
拿各个组件来讲可以理解为
- spider使用yeild将request发送给engine
- engine将request发送给scheduler
- scheduler,生成request交给engine
- engine拿到request,通过middleware发送给downloader
- downloader进行下载,在获取到response之后,又经过middleware发送给engine
- engine获取到response之后,返回给spider,spider的parse()方法对获取到的response进行处理,解析出items或者requests
- 将解析出来的items或者requests发送给engine
- engine获取到items或者requests,将items发送给ItemPipeline,将requests发送给scheduler(当只有调度器中不存在request时,程序才停止,及时请求失败scrapy也会重新进行请求)
简单整理一下各组件功能和实现情况
组件 | 功能 | 备注 |
---|---|---|
Scrapy Engine | 核心引擎 负责在不同模块和组件之间传递信号和数据 | scrapy默认实现 |
Scheduler | 请求调度器,存放来自引擎的请求,并在引擎请求时将它们排入队列 | scrapy默认实现 |
Downloader | 下载器,下载引擎发送过来的请求 并返回给引擎 | scrapy默认实现 |
Spider | 爬虫,编写请求,同时处理引擎发送过来的 response,后可以再次发送至引擎 | 需要自己实现 |
Item Pipeline | 数据管道,处理引擎发送过来的数据,例如进行存储 | 需要自己实现 |
Middlewares | 中间件,可实现过滤和拦截,默认是有 Downloader Middlewares和 Spider MiddlewaresSpider | 非必要实现,根据需求实现 |
四、scrapy和常规使用和使用小技巧
小技巧
- scrapy 使用item和ItemPipeline进行MySQL存储
笔者这里使用的是Python3的PyMySQL,需要读者根据自身环境自行安装。
修改item.py和piplines.py,在item.py填写自己需要的字段,这里的item定义好的字段要在spider进行组装。
item.py
import scrapy
class DemoItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field()
href = scrapy.Field()
pass
piplines.py
import pymysql
class YunzexiaoPipeline:
def __init__(self):
self.conn = pymysql.connect(
host='localhost',
port=3306,
user='root',
passwd='root',
db='test',
charset="utf8")
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
insert_sql = """
insert into baidu(title,href)values (%s,%s)
"""
# 插入数据
self.cursor.execute(insert_sql,(item['title'],item['href']))
self.conn.commit()
return item
def __del__(self):
#关闭操作游标
self.cursor.close()
#关闭数据库连接
self.conn.close()
再次运行爬虫,pipelines会进行数据存储。
- scrapy callbak 函数传参方法
借助cb_kwargs 进行传参
add_params = {'index': index}
yield scrapy.Request(url, callback=self.page_content, cb_kwargs=add_params)
# index 就是下传的参数 可以多个传参
def page_content(self, response, index):
print(index)
pass
- scrapy 运行不输出日志
scrpay crawl spider_name -s LOG_FILE=all.log
- scrapy 设置时间间隔和简单防爬
DOWNLOAD_DELAY = 2
RANDOMIZE_DOWNLOAD_DELAY = True
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'
COOKIES_ENABLED = True
或者设计随机请求间隔
from random import random
DOWNLOAD_DELAY = random()*5
随机请求头
# 1.在 settings 中添加
USER_AGENT_LIST=[
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
# 2.在 middlewares 中添加中间件
# 引入部分
from settings import USER_AGENT_LIST
import random
class RandomUserAgentMiddleware(object):
def process_request(self, request, spider):
rand_use = random.choice(USER_AGENT_LIST)
if rand_use:
request.headers.setdefault('User-Agent', rand_use)
- scrapy 解析返回内容技巧
- 使用css 进行解析 例如response.css(“li.hotsearch-item”):
- 使用Xpath进行解析
- 使用python的正则模块进行匹配