by 戴景波
Scrapy 框架實現爬蟲的基本原理
Scrapy 就是封裝好的框架,你可以專心編寫爬蟲的核心邏輯,無需自己編寫與爬蟲邏輯無關的代碼,套用這個框架就可以實現以上功能——爬取到想要的數據。
Scrapy是一個Python實現的輕量級爬蟲框架,它借助Twisted實現異步抓取。
Scrapy 是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。
本文檔將通過介紹Scrapy背后的概念使您對其工作原理有所了解,如果暫時理解不深也沒關系,后邊會結合實例具體介紹。
Python 爬蟲基本流程
A 發起請求———B 解析內容———C 獲取響應內容———D 保存數據
A 通過 HTTP 向目標站點發起請求,即發送一個 Request ,請求可以包含額外的 headers 等信息,等待服務器響應。
B 得到的內容可能是 HTML ,可以用正則表達式、網頁解析庫進行解析。可能是 Json ,可以直接轉為 Json 對象解析,可能是二進制數據,可以做保存或者進一步的處理。
C 如果服務器能正常響應,會得到一個 Response , Response 的內容便是所要獲取的頁面內容,類型可能有 HTML , Json 字符串,二進制數據(如圖片視頻)等類型。
D 保存形式多樣,可以存為文本,也可以保存至數據庫,或者保存特定格式的文件。
搭建自己本機環境如下:Windows7 64bit———Python3.7———Pycharm64
安裝 Python———安裝 Pycharm———安裝 Scrapy———新建爬蟲項目
簡單解釋:將 Python 比作 Java ,那么 Pycharm 就相當於 eclipse , Pycharm 就是 Python 語言的運行環境 IDE 工具。
安裝 Python
在 Python 的官網 www.python.org 中找到最新版本的 Python 安裝包,點擊進行下載,請注意,當你的電腦是32位的機器,請選擇32位的安裝包,如果是64位的,請選擇64位的安裝包;
我自己機器是 win7 64bit 所以我下載的是 python-3.7.4.amd64.exe,其中的 add python 3.7 to PATH 一定要勾選。
另外安裝 python 路徑不要有中文和空格,避免以后麻煩。后邊就點擊下一步即可。
如果忘記勾選則需要手動添加環境變量:(需要添加兩個: c:\python3.7.0;c:\python3.7.0\Scripts)
右鍵計算機——點擊屬性——點擊高級系統設置——高級——環境變量——用戶變量——PATH 添加自己安裝 python 的路徑。
安裝 Pycharm
本篇對於環境的搭建只是起到拋磚引玉的作用,建議大家以下邊做參考。
https://www.runoob.com/w3cnote/pycharm-windows-install.html
安裝 Scrapy
由於安裝 Scrapy 不是本系列重點,所以僅展示 Windows 系統上安裝 Scrapy 的步驟。注意:一定按順序安裝。 Cmd 進入 dos 窗口:
C:\Users\Administrator>python
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
C:\Users\Administrator>python -m pip -V
pip 19.0.3 from c:\python3.7.0\lib\site-packages\pip (python 3.7)
1.python -m pip install --upgrade pip
2.python -m pip install Twisted-18.9.0-cp37-cp37m-win_amd64.whl
3.python -m pip install pypiwin32
4.python -m pip install scrapy
5.python -m pip install requests
如果中途安裝遇到問題請及時 Google 查閱資料,查閱就是積累的過程。
Scrapy 創建新項目:
Pycharm 中用 alt+F12 切換到命令行,在命令行輸入:
(venv2) E:\>scrapy startproject peilv
就會生成 Scrapy 項目,項目名稱是 peilv ,結構如下:主要改寫2個文件:“items、settings”,新增2個文件:“爬蟲主程序”、itemcsvexporter。
peilv
scrapy.cfg #創建項目時自動生成,項目的配置文件
peilv/
__init__.py #創建項目時自動生成,無需任何改動
items.py #創建項目時自動生成,定義爬取的字段
pipelines.py #創建項目時自動生成,如存入文件,無需任何改動
settings.py #創建項目時自動生成,將爬取字段按順序輸出
middlewares.py #創建項目時自動生成,無需任何改動
spiders/
__init__.py #創建項目時自動生成,無需任何改動
itemcsvexporter.py #需自己編寫,代碼固定
爬蟲主程序.py #需自己編寫,爬蟲的主程序
items.py:
## -*- coding: utf-8 -*-
import scrapy
class PeilvItem(scrapy.Item):
# define the fields for your item here like:
cc = scrapy.Field()#changci
li = scrapy.Field()#libo
b5 = scrapy.Field()#bet365
以上是定義您想抓取的數據,在Scrapy中, 這是通過 Scrapy Items 來完成的。通過scrapy.Field()方法創建需要存儲的字段,比如cc存儲比賽的場次信息,li存儲立博的賠率信息,等等。
關於這個items.py,你只要考慮它就是一個存儲數據的容器,可以考慮成一個結構體,你所有需要提取的信息都在這里面存着。
這里我們需要存儲3個變量,cc,li,b5,所以我在里面加入三個變量,就這么簡單。
pipelines.py:
一般來說,如果你要操作數據庫什么的,需要在這里處理items,你可以把items寫入數據庫,但是今天我們用不到數據庫,scrapy自帶了一個很好的功能就是Feed exports,它支持多種格式的自動輸出。
所以我們直接用這個就好了,pipelines維持不變。
settings.py:
## -*- coding: utf-8 -*-
FEED_EXPORT_ENCODING = "gb18030" #解決導出的 Excel 文件中文亂碼問題
...
FEED_EXPORTERS = {
'csv': 'peilv.spiders.itemcsvexporter.itemcsvexporter',
}
FIELDS_TO_EXPORT = [
'cc',#比賽場次
'li',#立博的賠率
'b5',#bet365的賠率
]
...
FEED_EXPORT_ENCODING用gb18030常量來解決中文亂碼問題,FEED_EXPORTERS表明了輸出文件的格式,FIELDS_TO_EXPORT給定了輸出字段的順序。
itemcsvexporter.py:
from scrapy.conf import settings
from scrapy.exporters import CsvItemExporter
#指定輸出到 csv 文件中字段的順序,結合 setting.py
class itemcsvexporter(CsvItemExporter):
def __init__(self, *args, **kwargs):
...
這里需要注意的是有的版本不支持from scrapy.contrib.exporter import CsvItemExporter類,所以用from scrapy.exporters import CsvItemExporter替換即可。
通常結合setting中的字段順序,規定最終CSV文件中的列排序規則。
爬蟲主程序.py:(下一篇詳細介紹)
## -*- coding: utf-8 -*-
ls_url = 'https://live.leisu.com/wanchang?date='#ls歷史https://live.leisu.com/wanchang?date=20190606
class LiveJiangSpider(scrapy.Spider):
name = 'FBP'
allowed_domains = ['leisu.com']
def start_requests(self):
d1='20190606' #歷史的比賽
request = scrapy.http.FormRequest(ls_url + d1,callback=self.parseLs, meta={'d1': d1}) #歷史的比賽
# request = scrapy.http.FormRequest(wl_url + d1,callback=self.parseWl, meta={'d1': d1})#未來的比賽
yield request
def parseLs(self,response):
d2=response.meta['d1']
sel=response.xpath
racelist=[e5.split("'") for e5 in sel('//li[@data-status="8"]/@data-id').extract()]
for raceid in racelist:#raceid=['2674547'];raceid[0]=2674547
item = PeilvItem()
sel_div=sel('//li[@data-id='+str(raceid[0])+']/div[@class="find-table layout-grid-tbody hide"]/div[@class="clearfix-row"]')
if str(sel_div.xpath('span[@class="lab-lottery"]/span[@class="text-jc"]/text()').extract()) == "[]":
item['cc']=""
else:
item['cc']=str(d2) + str(sel_div.xpath('span[@class="lab-lottery"]/span[@class="text-jc"]/text()').extract()[0])
if "周" in item['cc']:#取競彩-周一001等
plurl='https://live.leisu.com/3in1-'+raceid[0]
request = scrapy.http.FormRequest(plurl,callback=self.parse,meta={'item':item})
yield request #並非return,yield壓隊列,parse函數將會被當做一個生成器使用。scrapy會逐一獲取parse方法中生成的結果,並沒有直接執行parse,循環完成后,再執行parse
def parse(self, response):
print('--------------into parse----------------------')
item = response.meta['item']
pv=response.xpath
pl_str = '/td[@class="bd-left"]/div[@class="begin float-left w-bar-100 bd-bottom p-b-8 color-999 m-b-8"]/span[@class="float-left col-3"]/text()'
if str(pv('//*[@data-id="5"]'+pl_str).extract())=="[]":
item['li'] = ''
else:
item['li']=pv('//*[@data-id="5"]' + pl_str).extract()[0]
if str(pv('//*[@data-id="2"]'+pl_str).extract())=="[]":
item['b5'] = ''
else:
item['b5']=pv('//*[@data-id="2"]' + pl_str).extract()[0]
yield item#程序在取得各個頁面的items前,會先處理完之前所有的request隊列里的請求,然后再提取items
爬蟲主程序實現了爬取網頁數據的具體邏輯,在下一講會結合一個具體事例詳細介紹。
改寫完程序后,最終執行命令:
Pycharm 用 alt+F12 切換到命令行在項目 peilv 路徑上執行:
(venv2) E:\>cd peilv\peilv
(venv2) E:\peilv\peilv>scrapy crawl FBP -o BaseData.csv
其中 FBP 是在“爬蟲主程序.py”定義的——name = 'FBP',“-o BaseData.csv” 是將爬取的數據輸出到 csv 文件中。
總結
以上首先創建一個工程和Spider模板,然后編寫Spider,編寫Item Pipeline,借助了Scrapy中的三個類——Request類、Response類和Item類。
同時我們以一個實戰項目為依托,將建立 Scrapy 項目的過程從零開始,深入淺出,讓讀者能夠實踐爬蟲的整個過程。
代碼地址
關注公眾號:python技術,回復"python"一起學習交流