scrapy框架入門
scrapy框架入門
一、Scrapy框架介紹
1.框架簡介
- Scrapy是純Python開發的一個高效,結構化的網頁抓取框架
- Scrapy使用了Twisted 異步網絡庫來處理網絡通訊
- Scrapy是為了爬取網站數據,提取結構性數據而編寫的應用框架
- Scrapy用途廣泛,可以用于數據挖掘、監測和自動化測試
2.模塊安裝
scrapy支持Python2.7和python3.4以上版本
python包可以用全局安裝(也稱為系統范圍),也可以安裝在用戶空間中
(1).Windows
pip install scrapy
換源:
pip install scrapy -i https://pypi.doubanio.com/simple
如果安裝途中報錯,則按照以下方法安裝
- 在
https://www.lfd.uci.edu/~gohlke/pythonlibs/
下載對應的Twisted的版本文件 - 在命令行進入到Twisted的目錄,執行
pip install Twisted的文件名
- 執行
pip install scrapy
(2).Ubuntu 14.04或以上
scrapy目前正在使用最新版的lxml,twisted和pyOpenSSL進行測試,并且與最近的Ubuntu發行版兼容,但它也支持舊版本的Ubuntu,比如Ubuntu14.04,盡管可能存在TLS連接問題
Ubuntu安裝不要使用 python-scrapyUbuntu提供的軟件包,它們通常太舊而且速度慢,無法趕上最新的Scrapy
-
在Ubuntu(或基于Ubuntu)系統上安裝scrapy,需要安裝這些依賴項:
sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
-
如果想在python3上安裝scrapy,還需要Python3的開發頭文件:
sudo apt-get install python3-dev
-
在virtualenv中,可以使用pip安裝Scrapy:
pip install scrapy
3.架構介紹
-
Engine:引擎。負責控制系統所有組件之間的數據流,并在發生某些操作時觸發事件,是整個框架的核心
-
Spiders:蜘蛛。由用戶編寫的自定義的類,用于解析響應,從中提取數據,或其它要抓取的請求
-
Scheduler:調度器。接收來自引擎的請求并將其排入隊列,在引擎再次請求時將請求提供給引擎
-
Downloader:下載器。獲取網頁并將其提供給引擎,引擎再將網頁內容提供給spider
-
Item Pipeline:項目管道。負責由爬蟲提取的數據的后續處理,典型的任務包括清理、驗證和存儲數據
-
Spider Middlewares:蜘蛛中間件。位于引擎和爬蟲之間的特定的鉤子,負責處理向蜘蛛輸入的響應和輸出的結果及新的請求。以下情況使用爬蟲中間件:
- 處理爬蟲回調之后的請求或item
- 處理start_requests
- 處理爬蟲異常
- 根據響應內容調用errback而不是回調請求
-
Downloader Middlewares:下載中間件。位于引擎和下載器之間的特定的鉤子,負責處理從引擎傳遞到下載器的請求,以及下載器傳遞到引擎的響應。以下情況使用下載中間件:
- 在請求發送到下載程序之前處理請求(即在scrapy將請求發送到網站之前)
- 在響應發送給爬蟲之前
- 直接發送新的請求,而不是將收到的響應傳遞給蜘蛛
- 將響應傳遞給爬行器而不獲取web頁面;
- 默默的放棄一些請求
-
Items:項目。定義了爬取結果的數據結構,爬取的數據會被賦值成該Item對象
-
Internet:事件驅動的網絡。scrapy 是用Twisted編寫的,Twisted是一個流行的事件驅動的Python網絡框架,它使用非阻塞(也成為異步)代碼實現并發
4.運行流程
Scrapy中的數據流由執行引擎控制,流程如下:
- 引擎首先打開一個網站,找到處理該網站的蜘蛛,并向該蜘蛛請求第一個要爬取的URL
- 引擎從蜘蛛獲取到第一個要爬取的URL,并通過調度器以Request的形式調度
- 引擎向調度器請求下一個要爬取的URL,調度器返回下一個需要爬取的URL給引擎
- 引擎將URL通過下載中間件轉發給下載器,下載器開始下載
- 一旦頁面下載完成,下載器生成該頁面的Response,并將其通過下載中間件發送給引擎
- 引擎從下載器接收到Response,然后通過蜘蛛中間件發送給蜘蛛進行處理
- 蜘蛛處理接收到的Response,然后解析出Item和生成新的Request,并發送給引擎
- 引擎將處理好的Item發送給Item Pipeline,將生成好的新的Request發送給調度器
- 重復2-8步,直至調度器中沒有Request為止,引擎關閉該網站
5.項目結構
scrapy.cfg # Scrapy項目的配置文件,定義了項目配置文件路徑、部署相關信息等內容
project/ # 項目模塊
__init__.py
items.py # 定義Item的數據結構
pipelines.py # 定義Item Pipeline的實現
settings.py # 定義項目的全局配置
middlewares.py # 定義爬蟲中間件和下載中間件的實現
spiders/ # 防止spider的文件夾
__init.py
spider1.py # spider1文件
spider2.py # spider2文件
...
二、Scrapy入門(爬取騰訊課堂所有python課程信息)
1.創建項目
進入你想要存放項目的目錄下運行一下命令:
scrapy startproject 項目名
例如:scrapy startproject tencent
該命令會在當前目錄創建包含一下文件的名為tz_spider的目錄
2.創建Spider
Spider是自己定義的類,Scrapy用它從網頁里抓取內容并解析抓取的結果。創建一個Spider的類,它必須必須繼承Scrapy提供的Spider類scrapy.Spider,并且需要定義三個屬性:
- name:用于區別Spider,該名字必須是唯一的
- start_urls:包含了Spider在啟動時進行爬取的url列表 ,初始請求由它定義
- parse(self, response) 方法:Spider的一個方法,每個初始url完成之后被調用。這個函數要完成兩個功能:
- 解析響應,封裝成item對象并返回這個對象
- 提取新的需要下載的url,創建新的request,并返回它
可以使用命令行創建一個spider:
cd 項目文件
scrapy genspider <name> <domain>
例如:
cd tencent
scrapy genspider ke ke.qq.com
會在spiders文件下創建ke.py文件,文件內容如下:
# -*- coding: utf-8 -*-
import scrapy
class KeSpider(scrapy.Spider):
name = 'ke'
allowed_domains = ['ke.qq.com']
start_urls = ['http://ke.qq.com/']
def parse(self, response):
pass
- allowed_domains:允許爬取的域名,如果初始或后續的請求鏈接不是這個域名下的,則會被過濾掉,一般將其注釋掉
3.定義Items文件
Item是保存爬取數據的容器,使用方法類似于字典,比字典多了額外的保護機制,避免拼寫錯誤或者定義字段錯誤。創建Item類需要繼承scrapy.Item類,并且定義類型為scrapy.Field的字段
items.py文件,內容如下:
import scrapy
class KeItem(scrapy.Item):
title = scrapy.Field()
link_url = scrapy.Field()
img_url = scrapy.Field(
4.解析Response
parse()方法的參數response是start_urls里面的鏈接爬取后的結果,所以可以在parse()方法中直接對response進行解析,extract()方法把selectlist對象序列成字符串
# -*- coding: utf-8 -*-
import scrapy
class KeSpider(scrapy.Spider):
name = 'ke'
# allowed_domains = ['ke.qq.com']
start_urls = ['https://ke.qq.com/course/list']
def parse(self, response):
title_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/h4/a/text()').extract()
link_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/@href').extract()
img_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/img/@src').extract()
5.使用Item
Item可以理解為一個字典,但在聲明的時候需要實例化,因此首先導入該類,接下來進行實例化,然后依次用剛才解析的結果賦值給Item的每個字段,最后將Item通過yield返回即可。這樣首頁的所有內容都被解析出來,并且復制成一個個的KeItem()
# -*- coding: utf-8 -*-
import scrapy
from ..items import KeItem
class KeSpider(scrapy.Spider):
name = 'ke'
# allowed_domains = ['ke.qq.com']
start_urls = ['https://ke.qq.com/course/list']
def parse(self, response):
title_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/h4/a/text()').extract()
link_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/@href').extract()
img_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/img/@src').extract()
for title, link_url, img_url in zip(title_list, link_url_list, img_url_list):
item = KeItem()
item['title'] = title
item['link_url'] = link_url
item['img_url'] = img_url
yield item
6.后續Request
上面的爬蟲實現了從初始頁面抓取內容,而我們需要爬取所有頁面,直到所有的信息都被下載。因此需要從頁面中提取鏈接,或者根據規則構建(小技巧:開發者工具下點擊下一頁那個標識)。構造請求時候需要用到scrapy.Request(),傳入兩個參數:
- url:請求鏈接
- callback:回調函數。當指定了該回調函數的請求完成后,獲取到響應,引擎會將該響應作為參數傳遞給此回調函數,回調函數進行解析或生成下一個請求
# -*- coding: utf-8 -*-
import scrapy
from ..items import KeItem
class KeSpider(scrapy.Spider):
name = 'ke'
# allowed_domains = ['ke.qq.com']
start_urls = ['https://ke.qq.com/course/list']
def parse(self, response):
title_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/h4/a/text()').extract()
link_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/@href').extract()
img_url_list = response.xpath('//ul/li[@class="course-card-item--v3 js-course-card-item "]/a/img/@src').extract()
for title, link_url, img_url in zip(title_list, link_url_list, img_url_list):
item = KeItem()
item['title'] = title
item['link_url'] = link_url
item['img_url'] = img_url
yield item
next_url = response.xpath('//a[@class="page-next-btn icon-font i-v-right"]/@href').extract_first() # 此處需要調用extract_first()方法獲取獲取內容
if next_url: # next_url為空時停止,否則報錯
yield scrapy.Request(url=next_url, callback=self.parse) # 回調函數依然使用parse()方法,不寫默認也是parse()方法
7.運行
進入項目根目錄(tencent)下,在命令行運行命令:
查看可運行的爬蟲文件:
scrapy list
運行爬蟲:
scrapy crawl <name>
注意:此處的name是創建Spider時的name屬性,而不是.py文件的文件名
例如:scrapy crawl ke
8.保存到文件
以下命令對應的輸出分別為json、csv、xml、pickle、marshal格式
scrapy crawl ke -o ke.json
scrapy crawl ke -o ke.csv
scrapy crawl ke -o ke.xml
scrapy crawl ke -o ke.pickle
scrapy crawl ke -o ke.marshal
9.定義Item Pipeline
如果想進行更復雜的操作(將結果保存到數據庫,或者篩選信息),則需要定義Item Pipeline來實現
Item Pipeline的主要用途是:
- 清理HTML數據
- 驗證爬取數據,檢查爬取字段
- 查重并刪除重復內容
- 將爬取結果保存到數據庫
要**這個管道組件,必須將其添加到ITEM_PIPELINES設置中,在settings文件中設置如下:
ITEM_PIPELINES = {
'tencent.pipelines.TencentPipeline': 300,
}
編寫一個用來存儲課程信息到ke.json文件中的管道類,修改項目下piplines.py文件
import json
class TencentPipeline(object):
def open_spider(self, spider):
# 在爬蟲啟動時打開文件
# 打開文件句柄
self.f = open('ke.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
# 處理傳遞過來的item
self.f.write(json.dumps(dict(item), ensure_ascii=False, indent=4) + "\n")
return item
def close_spider(self, spider):
# 在爬蟲關閉時關閉文件
self.f.close()
柄
self.f = open(‘ke.json’, ‘w’, encoding=‘utf-8’)
def process_item(self, item, spider):
# 處理傳遞過來的item
self.f.write(json.dumps(dict(item), ensure_ascii=False, indent=4) + "\n")
return item
def close_spider(self, spider):
# 在爬蟲關閉時關閉文件
self.f.close()
智能推薦
Python爬蟲day7—Scrapy框架入門
Scrapy爬蟲框架入門 概述 Scrapy是Python開發的一個非常流行的網絡爬蟲框架,可以用來抓取Web站點并從頁面中提取結構化的數據,被廣泛的用于數據挖掘、數據監測和自動化測試等領域。下圖展示了Scrapy的基本架構,其中包含了主要組件和系統的數據處理流程(圖中帶數字的紅色箭頭)。 組件 Scrapy引擎(Engine):Scrapy引擎是用來控制整個系統的數據處理流程。 調度器(Sche...
Python爬蟲學習教程:Scrapy爬蟲框架入門
Python爬蟲學習教程:Scrapy概述 Scrapy是Python開發的一個非常流行的網絡爬蟲框架,可以用來抓取Web站點并從頁面中提取結構化的數據,被廣泛的用于數據挖掘、數據監測和自動化測試等領域。下圖展示了Scrapy的基本架構,其中包含了主要組件和系統的數據處理流程(圖中帶數字的紅色箭頭)。 組件 Scrapy引擎(Engine):Scrapy引擎是用來控制整個系統的數據處理流程。 調度...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
猜你喜歡
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...