Scrapy介紹
Scrapy是用純Python實現一個為了爬取網站數據、提取結構性數據而編寫的應用框架,用途非常廣泛。
框架的力量,用戶只需要定制開發幾個模塊就可以輕松的實現一個爬蟲,用來抓取網頁內容以及各種圖片,非常之方便。
Scrapy 使用了 Twisted異步網絡框架來處理網絡通訊,可以加快我們的下載速度,不用自己去實現異步框架,並且包含了各種中間件接口,可以靈活的完成各種需求。
Scrapy架構圖
Scrapy Engine(引擎): 用來處理整個系統的數據流處理, 觸發事務(框架核心)
Scheduler(調度器): 用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什么, 同時去除重復的網址
Downloader(下載器):負責下載Scrapy Engine(引擎)發送的所有Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
Spider(爬蟲):爬蟲是主要干活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
Item Pipeline(管道):負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析后,將被發送到項目管道,並經過幾個特定的次序處理數據。
Downloader Middlewares(下載中間件):位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
Spider Middlewares(調度中間件):介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。
Scrapy運行流程
- 首先,引擎從調度器中取出一個鏈接(URL)用於接下來的抓取
- 引擎把URL封裝成一個請求(Request)傳給下載器,下載器把資源下載下來,並封裝成應答包(Response)
- 然后,爬蟲解析Response
- 若是解析出實體(Item),則交給實體管道進行進一步的處理。
- 若是解析出的是鏈接(URL),則把URL交給Scheduler等待抓取
安裝
Linux安裝:
pip3 install scrapy
Windows安裝:
# 1. pip3 install wheel # 2. 下載twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted # 3. 進入下載目錄,執行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl # 4. pip3 install pywin32 # 5. pip3 install scrapy
命令行工具
# 1 查看幫助 scrapy -h scrapy <command> -h # 2 有兩種命令:其中Project-only必須切到項目文件夾下才能執行,而Global的命令則不需要 Global commands: startproject #創建項目 genspider #創建爬蟲程序 settings #如果是在項目目錄下,則得到的是該項目的配置 runspider #運行一個獨立的python文件,不必創建項目 shell #scrapy shell url地址 在交互式調試,如選擇器規則正確與否 fetch #獨立於程單純地爬取一個頁面,可以拿到請求頭 view #下載完畢后直接彈出瀏覽器,以此可以分辨出哪些數據是ajax請求 version #scrapy version 查看scrapy的版本,scrapy version -v查看scrapy依賴庫的版本 Project-only commands: crawl #運行爬蟲,必須創建項目才行,確保配置文件中ROBOTSTXT_OBEY = False check #檢測項目中有無語法錯誤 list #列出項目中所包含的爬蟲名 edit #編輯器,一般不用 parse #scrapy parse url地址 --callback 回調函數 #以此可以驗證我們的回調函數是否正確 bench #scrapy bentch壓力測試
Scrapy框架官方網址:http://doc.scrapy.org/en/latest
Scrapy中文維護站點:http://scrapy-chs.readthedocs...
目錄結構
project_name/ scrapy.cfg # 項目的主配置信息,用來部署scrapy時使用,爬蟲相關的配置信息在settings.py文件中。 project_name/ __init__.py items.py # 設置數據存儲模板,用於結構化數據,如:Django的Model pipelines.py # 項目管道文件,如:一般結構化的數據持久化 settings.py # 配置文件,如:遞歸的層數、並發數,延遲下載等。 spiders/ # 爬蟲目錄,如:創建文件,編寫爬蟲規則 __init__.py 爬蟲1.py 爬蟲2.py 爬蟲3.py
注意:
1. 一般創建爬蟲文件時,以網站域名命名
2. 默認只能在終端執行命令,為了更便捷操作:
如果想在pycharm中執行需要做:
#在項目目錄下新建:entrypoint.py from scrapy.cmdline import execute # execute(['scrapy', 'crawl', 'amazon','--nolog']) #不要日志打印 # execute(['scrapy', 'crawl', 'amazon']) #我們可能需要在命令行為爬蟲程序傳遞參數,就用下面這樣的命令 #acrapy crawl amzaon -a keyword=iphone8 execute(['scrapy', 'crawl', 'amazon1','-a','keyword=iphone8','--nolog']) #不要日志打印 # execute(['scrapy', 'crawl', 'amazon1'])
項目實戰
scrapy startproject Qiubai # 創建項目 cd Qiubai # 進入項目目錄 scrapy genspider qiubai www.qiushibaike.com # 應用名稱 爬取網頁的起始url
2 編寫爬蟲文件:在步驟2執行完畢后,會在項目的spiders中生成一個應用名的py爬蟲文件,文件源碼如下:
import scrapy class QiubaiSpider(scrapy.Spider): name = 'qiubai' # 應用名稱 # 允許爬取的域名(如果遇到非該域名的url則爬取不到數據) allowed_domains = ['https://www.qiushibaike.com/'] start_urls = ['https://www.qiushibaike.com/'] # 起始爬取的url def parse(self, response): # xpath為response中的方法,可以將xpath表達式直接作用於該函數中 odiv = response.xpath('//div[@id="content-left"]/div') content_list = [] # 用於存儲解析到的數據 for div in odiv: # xpath函數返回的為列表,列表中存放的數據為Selector類型的數據。我們解析到的內容被封裝在了Selector對象中,需要調用extract()函數將解析的內容從Selecor中取出。 author = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0].extract() content=div.xpath('.//div[@class="content"]/span/text()')[0].extract() # 將解析到的內容封裝到字典中 dic={ '作者':author, '內容':content } # 將數據存儲到content_list這個列表中 content_list.append(dic) return content_list
3 設置修改settings.py配置文件相關配置,修改內容及其結果如下:
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' #偽裝請求載體身份 ROBOTSTXT_OBEY = False # 可以忽略或者不遵守robots協議
4 執行爬蟲程序:
scrapy crawl 爬蟲名稱 # 該種執行形式會顯示執行的日志信息 scrapy crawl 爬蟲名稱 --nolog # 該種執行形式不會顯示執行的日志信息
最后
今天是情人節,祝大家情人節快樂
有對象的已經去跟對象去約會了,愛學習的才會跟代碼相伴(比如我)
送大家一段 python 的情人節代碼吧:
print("\n".join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 <= 0 else ' ') for x in range(-30, 30)]) for y in range(30, -30, -1)]))
好奇的去copy運行一下吧~