Scrapy是什么?
Scrapy是一個由Python編寫的開源協(xié)作爬蟲框架,可以快速的從網(wǎng)站中提取需要的數(shù)據(jù)。Scrapy基礎(chǔ)爬蟲部分內(nèi)部已經(jīng)實現(xiàn),只需編寫采集規(guī)則即可,簡單易用,擴展性強,多平臺運行兼容性好。
詳細筆者不做介紹,dddd(懂的都懂 哈哈)
scrapy官網(wǎng): https://scrapy.org/
github地址:https://github.com/scrapy/scrapy
一、Scrapy安裝
1.安裝 lxml:pip3 install lxml。
2.安裝pyOpenSSL:在官網(wǎng)下載wheel文件。
3.安裝Twisted:在官網(wǎng)下載wheel文件。
4.安裝PyWin32:在官網(wǎng)下載wheel文件
5.最后安裝 scrapy,pip3 install scrapy
注意: 2、3、4如果采用pip3在線安裝失敗 可以采用下載后 pip install +文件路徑/文件名進行安裝
下載地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
二、Scrapy基本使用
- scrapy 創(chuàng)建項目
scrapy startproject projecname
得到一下目錄
└─projecname
│ scrapy.cfg #開發(fā)配置文件
│
└─projecname #工程模塊
│ items.py #獲取定義模塊 定義使用的字段
│ middlewares.py #中間件 定義中間件
│ pipelines.py #處理數(shù)據(jù)
│ settings.py #工程設(shè)置文件
│ __init__.py #空文件
│
├─spiders #爬蟲目錄,用于放置各種爬蟲類文件
│ │ __init__.py #空文件
- 新建一個爬蟲
在spiders文件夾下創(chuàng)建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
image
一個簡單的demo就完成了
三、Scrapy基本介紹
官網(wǎng)給出的數(shù)據(jù)流圖和解釋
image
Scrapy 中的數(shù)據(jù)流由執(zhí)行引擎控制,如下所示:
- 引擎獲取最初的請求進行爬行。
- 引擎將請求發(fā)送至調(diào)度器。
- 調(diào)度器調(diào)度將請求發(fā)送引擎。
- 引擎將請求通過下載器中間件發(fā)送到下載器。
- 頁面完成下載后, 下載器生成一個響應(yīng)(帶有該頁面)通過下載器中間件將其發(fā)送到引擎。
- 該引擎接收來自響應(yīng),下載器將其發(fā)送到爬蟲進行處理,其中通過爬蟲中間件。
- 爬蟲處理響應(yīng)并返回項目和新的請求。
- 引擎發(fā)送處理好的數(shù)據(jù),然后把處理的請求的調(diào)度,并請求下一個可能的爬蟲請求。
- 該過程重復(fù)(從第 1 步開始),直到不再有來自Scheduler 的請求。
拿各個組件來講可以理解為
- spider使用yeild將request發(fā)送給engine
- engine將request發(fā)送給scheduler
- scheduler,生成request交給engine
- engine拿到request,通過middleware發(fā)送給downloader
- downloader進行下載,在獲取到response之后,又經(jīng)過middleware發(fā)送給engine
- engine獲取到response之后,返回給spider,spider的parse()方法對獲取到的response進行處理,解析出items或者requests
- 將解析出來的items或者requests發(fā)送給engine
- engine獲取到items或者requests,將items發(fā)送給ItemPipeline,將requests發(fā)送給scheduler(當(dāng)只有調(diào)度器中不存在request時,程序才停止,及時請求失敗scrapy也會重新進行請求)
簡單整理一下各組件功能和實現(xiàn)情況
| 組件 | 功能 | 備注 |
|---|---|---|
| Scrapy Engine | 核心引擎 負責(zé)在不同模塊和組件之間傳遞信號和數(shù)據(jù) | scrapy默認實現(xiàn) |
| Scheduler | 請求調(diào)度器,存放來自引擎的請求,并在引擎請求時將它們排入隊列 | scrapy默認實現(xiàn) |
| Downloader | 下載器,下載引擎發(fā)送過來的請求 并返回給引擎 | scrapy默認實現(xiàn) |
| Spider | 爬蟲,編寫請求,同時處理引擎發(fā)送過來的 response,后可以再次發(fā)送至引擎 | 需要自己實現(xiàn) |
| Item Pipeline | 數(shù)據(jù)管道,處理引擎發(fā)送過來的數(shù)據(jù),例如進行存儲 | 需要自己實現(xiàn) |
| Middlewares | 中間件,可實現(xiàn)過濾和攔截,默認是有 Downloader Middlewares和 Spider MiddlewaresSpider | 非必要實現(xiàn),根據(jù)需求實現(xiàn) |
四、scrapy和常規(guī)使用和使用小技巧
小技巧
- scrapy 使用item和ItemPipeline進行MySQL存儲
筆者這里使用的是Python3的PyMySQL,需要讀者根據(jù)自身環(huán)境自行安裝。
修改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)
"""
# 插入數(shù)據(jù)
self.cursor.execute(insert_sql,(item['title'],item['href']))
self.conn.commit()
return item
def __del__(self):
#關(guān)閉操作游標(biāo)
self.cursor.close()
#關(guān)閉數(shù)據(jù)庫連接
self.conn.close()
再次運行爬蟲,pipelines會進行數(shù)據(jù)存儲。
- scrapy callbak 函數(shù)傳參方法
借助cb_kwargs 進行傳參
add_params = {'index': index}
yield scrapy.Request(url, callback=self.page_content, cb_kwargs=add_params)
# index 就是下傳的參數(shù) 可以多個傳參
def page_content(self, response, index):
print(index)
pass
- scrapy 運行不輸出日志
scrpay crawl spider_name -s LOG_FILE=all.log
- scrapy 設(shè)置時間間隔和簡單防爬
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
或者設(shè)計隨機請求間隔
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 解析返回內(nèi)容技巧
- 使用css 進行解析 例如response.css("li.hotsearch-item"):
- 使用Xpath進行解析
- 使用python的正則模塊進行匹配