Scrapy爬蟲及案例剖析

因爲互聯網的極速發展,全部如今的信息處於大量堆積的狀態,咱們既要向外界獲取大量數據,又要在大量數據中過濾無用的數據。針對咱們有益的數據須要咱們進行指定抓取,從而出現瞭如今的爬蟲技術,經過爬蟲技術咱們能夠快速獲取咱們須要的數據。可是在這爬蟲過程當中,信息擁有方會對爬蟲進行反爬處理,咱們就須要對這些困難進行逐個擊破。css

恰好前段時間作了爬蟲相關的工做,這裏就記錄下一些相關的心得。html

本文案例代碼地址 https://github.com/yangtao9502/ytaoCrawlpython

這裏我是使用的 Scrapy 框架進行爬蟲,開發環境相關版本號:mysql

Scrapy       : 1.5.1
lxml         : 4.2.5.0
libxml2      : 2.9.8
cssselect    : 1.0.3
parsel       : 1.5.1
w3lib        : 1.20.0
Twisted      : 18.9.0
Python       : 3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)]
pyOpenSSL    : 18.0.0 (OpenSSL 1.1.1a  20 Nov 2018)
cryptography : 2.4.2
Platform     : Windows-10-10.0.15063-SP0

本地開發環境建議使用 Anaconda 安裝相關環境,不然可能出現各類依賴包的衝突,相信遇到過的都深有體會,在你配置相關環境的時候就失去爬蟲的興趣。 本文提取頁面數據主要使用 Xpath ,因此在進行文中案例操做前,先了解 Xpath 的基本使用。git

建立 Scrapy 項目

scrapy 建立項目很簡單,直接一條命令搞定,接下來咱們建立 ytaoCrawl 項目:github

scrapy startproject ytaoCrawl

注意,項目名稱必須以字母開頭,而且只包含字母、數字和下劃線。 建立成功後界面顯示:sql

初始化項目的文件有:數據庫

其中各個文件的用途:json

  • spider 目錄用於存放爬蟲文件。
  • items.py 文件最爲對象,將爬蟲數據保存在該對象中。
  • middlewares.py 文件爲中間件處理器,好比請求和響應的轉換都在裏面實現。
  • pipelines.py 文件爲數據管道,用於數據抓取後輸送。
  • settings.py 文件爲配置文件,爬蟲中的一些配置可在該文件中設置。
  • scrapy.cfg 文件爲爬蟲部署的配置文件。

瞭解幾個默認生成的文件後再看下面的 scrapy 結構原理圖,相對好理解。api

這樣咱們的一個 scrapy 爬蟲項目就此建立完成。

建立 Spider

咱們先建立一個 python 文件 ytaoSpider,該類必須繼承 scrapy.Spider 類。接下來咱們就以爬取北京 58 租房信息爲例進行分析。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 
# @Author  : YangTao
# @blog    : https://ytao.top
# 
import scrapy

class YtaoSpider(scrapy.Spider):
    # 定義爬蟲名稱
    name = "crawldemo"
    # 容許爬取的域名,但不包含 start_urls 中的連接
    allowed_domains = ["58.com"]
    # 起始爬取連接
    start_urls = [
        "https://bj.58.com/chuzu/?PGTID=0d100000-0038-e441-0c8a-adeb346199d8&ClickID=2"
    ]

    def download(self, response, fName):
        with open(fName + ".html", 'wb') as f:
            f.write(response.body)

    # response 是返回抓取後的對象
    def parse(self, response):
        # 下載北京租房頁面到本地,便於分析
        self.download(response, "北京租房")

經過執行命令啓動爬蟲,指定爬蟲名字:

scrapy crawl crawldemo

當咱們有多個爬蟲時,能夠經過 scrapy list 獲取全部的爬蟲名。

開發過程當中固然也能夠用 mian 函數在編輯器中啓動:

if __name__ == '__main__':
    name = YtaoSpider.name
    cmd = 'scrapy crawl {0} '.format(name)
    cmdline.execute(cmd.split())

這時將在咱們啓動的目錄中下載生成咱們爬取的頁面。

翻頁爬取

上面咱們只爬取到了第一頁,可是咱們實際抓取數據過程當中,一定會涉及到分頁,因此觀察到該網站的分頁是將最後一頁有展現出來(58最多隻展現前七十頁的數據),如圖。

從下圖觀察到分頁的 html 部分代碼。

接下來經過 Xpath 和正則匹配獲取最後一頁的頁碼。

def pageNum(self, response):
    # 獲取分頁的 html 代碼塊
    page_ele = response.xpath("//li[@id='pager_wrap']/div[@class='pager']")
    # 經過正則獲取含有頁碼數字的文本
    num_eles = re.findall(r">\d+<", page_ele.extract()[0].strip())
    # 找出最大的一個
    count = 0
    for num_ele in num_eles:
        num_ele = str(num_ele).replace(">", "").replace("<", "")
        num = int(num_ele)
        if num > count:
            count = num
    return count

經過對租房連接進行分析,能夠看出不一樣頁碼的連接爲https://bj.58.com/chuzu/pn+num 這裏的num表明頁碼,咱們進行不一樣的頁碼抓取時,只需更換頁碼便可,parse 函數可更改成:

# 爬蟲連接,不含頁碼
target_url = "https://bj.58.com/chuzu/pn"

def parse(self, response):
        print("url: ", response.url)
        num = self.pageNum(response)
        # 開始頁面原本就是第一頁,因此在遍歷頁面時,過濾掉第一頁
        p = 1
        while p < num:
            p += 1
            try:
                # 拼接下一頁連接
                url = self.target_url + str(p)
                # 進行抓取下一頁
                yield Request(url, callback=self.parse)
            except BaseException as e:
                logging.error(e)
                print("爬取數據異常:", url)

執行後,打印出的信息如圖:

由於爬蟲是異步抓取,因此咱們的打印出來的並不是有序數據。 上面所介紹的是經過獲取最後一頁的頁碼進行遍歷抓取,可是有些網站沒有最後一頁的頁碼,這時咱們能夠經過下一頁來判斷當前頁是否爲最後一頁,若是不是,就獲取下一頁所攜帶的連接進行爬取。

獲取數據

這裏咱們就獲取標題,面積,位置,小區,及價格信息,咱們須要先在 item 中建立這些字段,閒話少說,上代碼。

# 避免取xpath解析數據時索引越界
def xpath_extract(self, selector, index):
    if len(selector.extract()) > index:
        return selector.extract()[index].strip()
    return ""

def setData(self, response):
    items = []
    houses = response.xpath("//ul[@class='house-list']/li[@class='house-cell']")
    for house in houses:
        item = YtaocrawlItem()
        # 標題
        item["title"] = self.xpath_extract(house.xpath("div[@class='des']/h2/a/text()"), 0)
        # 面積
        item["room"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='room']/text()"), 0)
        # 位置
        item["position"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='infor']/a/text()"), 0)
        # 小區
        item["quarters"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='infor']/a/text()"), 1)
        money = self.xpath_extract(house.xpath("div[@class='list-li-right']/div[@class='money']/b/text()"), 0)
        unit = self.xpath_extract(house.xpath("div[@class='list-li-right']/div[@class='money']/text()"), 1)
        # 價格
        item["price"] = money+unit
        items.append(item)
    return items

def parse(self, response):
    items = self.setData(response)
    for item in items:
        yield item
    
    # 接着上面的翻頁操做 .....

至此,咱們以獲取咱們想要的數據,經過打印 parse 中的 item 可看到結果。

數據入庫

咱們已抓取到頁面的數據,接下來就是將數據入庫,這裏咱們以 MySQL 存儲爲例,數據量大的狀況,建議使用使用其它存儲產品。 首先咱們先在 settings.py 配置文件中設置 ITEM_PIPELINES 屬性,指定 Pipeline 處理類。

ITEM_PIPELINES = {
    # 值越小,優先級調用越高
   'ytaoCrawl.pipelines.YtaocrawlPipeline': 300,
}

在 YtaocrawlPipeline 類中處理數據持久化,這裏 MySQL 封裝工具類 mysqlUtils 代碼可在 github 中查看。 經過再 YtaoSpider#parse 中使用 yield 將數據傳輸到 YtaocrawlPipeline#process_item 中進行處理。

class YtaocrawlPipeline(object):

    def process_item(self, item, spider):
        table = "crawl"
        item["id"] = str(uuid.uuid1())
        # 若是當前爬取信息的連接在庫中有存在,那麼就刪除舊的再保存新的
        list = select(str.format("select * from {0} WHERE url = '{1}'", table, item["url"]))
        if len(list) > 0:
            for o in list:
                delete_by_id(o[0], table)
        insert(item, table)
        return item

在數據庫中,能夠看到成功抓取到數據併入庫。

反爬機制應對

既然有數據爬蟲的需求,那麼就必定有反扒措施,就當前爬蟲案例進行一下分析。

字體加密

經過上面數據庫數據的圖,能夠看到該數據中存在亂碼,經過查看數據亂碼規律,能夠定位在數字進行了加密。

同時,經過打印數據能夠看到\xa0字符,這個(表明空白符)在 ASCII 字符 0x20~0x7e 範圍,可知是轉換爲了 ASCII 編碼。

由於知道是字體加密,因此在下載的頁面查看font-family字體時,發現有以下圖所示代碼:

看到這個fangchan-secret字體比較可疑了,它是在js中動態生成的字體,且以 base64 存儲,將如下字體進行解碼操做。

if __name__ == '__main__':
    secret = "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"
    # 將字體文件編碼轉換爲 UTF-8 編碼的字節對象
    bytes = secret.encode(encoding='UTF-8')
    # base64位解碼
    decodebytes = base64.decodebytes(bytes)
    # 利用 decodebytes 初始化 BytesIO,而後使用 TTFont 解析字體庫
    font = TTFont(BytesIO(decodebytes))
    # 字體的映射關係
    font_map = font['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap

    print(font_map)

經過將 fontTools 庫的 TTFont 將字體進行解析,都到以下字體映射結果:

{
	38006: 'glyph00007',
	38287: 'glyph00005',
	39228: 'glyph00006',
	39499: 'glyph00003',
	40506: 'glyph00010',
	40611: 'glyph00001',
	40804: 'glyph00009',
	40850: 'glyph00004',
	40868: 'glyph00002',
	40869: 'glyph00008'
}

恰好十個映射,對應的 0~9 的數量,可是查找相應規律,1~9 後,出現了個 10,那麼這裏對應的數字究竟是一個怎麼樣的規律呢?還有上面映射對應的 key 不是16進制的 ASCII 碼,而是一個純數字,是否是多是十進制的碼呢? 接下來驗證咱們的設想,將頁面上獲取的十六進制的碼轉換成十進制的碼,而後去匹配映射中的數據,發現映射的值的非零數字部分恰好比頁面上對應的數字字符大 1 ,可知,真正的值須要咱們在映射值中減 1。 代碼整理後

def decrypt(self, response, code):
    secret = re.findall("charset=utf-8;base64,(.*?)'\)", response.text)[0]
    code = self.secretfont(code, secret)
    return code

def secretfont(self, code, secret):
    # 將字體文件編碼轉換爲 UTF-8 編碼的字節對象
    bytes = secret.encode(encoding='UTF-8')
    # base64位解碼
    decodebytes = base64.decodebytes(bytes)
    # 利用 decodebytes 初始化 BytesIO,而後使用 TTFont 解析字體庫
    font = TTFont(BytesIO(decodebytes))
    # 字體的映射關係
    font_map = font['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap
    chars = []
    for char in code:
        # 將每一個字符轉換成十進制的 ASCII 碼
        decode = ord(char)
        # 若是映射關係中存在 ASCII 的 key,那麼這個字符就有對應的字體
        if decode in font_map:
            # 獲取映射的值
            val = font_map[decode]
            # 根據規律,獲取數字部分,再減1獲得真正的值
            char = int(re.findall("\d+", val)[0]) - 1
        chars.append(char)
    return "".join(map(lambda s:str(s), chars))

如今,咱們將全部爬取的數據進行解密處理,再查看數據:

上圖中,進行解密後,完美解決數據亂碼!

驗證碼和封禁IP

驗證碼通常分爲兩類,一類是剛開始進入時,必須輸入驗證碼的,一類是頻繁請求後,須要驗證碼驗證再繼續接下來的請求。 對於第一種來講,就必須破解它的驗證碼才能繼續,第二種來講,除了破解驗證碼,還可使用代理進行繞過驗證。 對於封禁IP的反爬,一樣可以使用代理進行繞過。好比仍是使用上面的網址爬蟲,當它們識別到我多是爬蟲時,就會使用驗證碼進行攔截,以下圖:

接下來,咱們使用隨機 User-Agent 和代理IP進行繞行。 先設置 settings.USER_AGENT,注意PC端和移動端不要混合設置的 User-Agent,不然你會爬取數據會異常,由於不一樣端的頁面不一樣

USER_AGENT = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.10 Safari/537.36",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    # ......
]

在請求中設置隨機 User-Agent 中間件

class RandomUserAgentMiddleware(object):
    def __init__(self, agents):
        self.agent = agents

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            agents=crawler.settings.get('USER_AGENT')
        )

    def process_request(self, request, spider):
        # 隨機獲取設置中的一個 User-Agent
        request.headers.setdefault('User-Agent', random.choice(self.agent))

設置動態IP中間件

class ProxyIPMiddleware(object):
    def __init__(self, ip=''):
        self.ip = ip

    def process_request(self, request, spider):
        # 若是當前的地址重定向到了驗證碼地址,就使用代理ip進行從新請求
        if self.ban_url(request.url):
            # 獲取被重定向的地址
            redirect_urls = request.meta.get("redirect_urls")[0]
            # 將當前重定向到驗證碼的地址改成原始請求地址
            request._set_url(redirect_urls)
            # 設置動態代理,這裏在線上通常使用接口動態生成代理
            request.meta["proxy"] = "http://%s" % (self.proxy_ip())

    def ban_url(self, url):
        # settings中設置的驗證碼或被禁止的頁面連接,當遇到該連接時,爬蟲會進行繞行重爬
        dic = settings.BAN_URLS
        # 驗證當前請求地址是否爲驗證碼地址
        for d in dic:
            if url.find(d) != -1:
                return True
        return False

    # 代理動態生成的 ip:port
    def proxy_ip(self):
        # 模擬動態生成代理地址
        ips = [
            "127.0.0.1:8888",
            "127.0.0.1:8889",
        ]
        return random.choice(ips);

    def process_response(self, request, response, spider):
        # 若是不是成功響應,則從新爬蟲
        if response.status != 200:
            logging.error("失敗響應: "+ str(response.status))
            return request
        return response

最後在 settings 配置文件中開啓這些中間件。

DOWNLOADER_MIDDLEWARES = {
   'ytaoCrawl.middlewares.RandomUserAgentMiddleware': 500,
   'ytaoCrawl.middlewares.ProxyIPMiddleware': 501,
   'ytaoCrawl.middlewares.YtaocrawlDownloaderMiddleware': 543,
}

如今爲止,設置隨機 User-Agent 和動態IP繞行已完成。

部署

使用 scrapyd 部署爬蟲項目,能夠對爬蟲進行遠程管理,如啓動,關閉,日誌調用等等。 部署前,咱們得先安裝 scrapyd ,使用命令:

pip install scrapyd

安裝成功後,能夠看到該版本爲 1.2.1

部署後,咱們還須要一個客戶端進行訪問,這裏就須要一個 scrapyd-client 客戶端:

pip install scrapyd-client

修改 scrapy.cfg 文件

[settings]
default = ytaoCrawl.settings

[deploy:localytao]
url = http://localhost:6800/
project = ytaoCrawl

# deploy 可批量部署

啓動 scrapyd:

scrapyd

若是是 Windows,要先在X:\xx\Scripts下建立scrapyd-deploy.bat文件

@echo off
"X:\xx\python.exe" "X:\xx\Scripts\scrapyd-deploy" %1 %2

項目部署到 Scrapyd 服務上:

scrapyd-deploy localytao -p ytaoCrawl

遠程啓動 curl http://localhost:6800/schedule.json -d project=ytaoCrawl -d spider=ytaoSpider

執行啓動後,能夠在http://localhost:6800/中查看爬蟲執行狀態,以及日誌

除了啓動可遠程調用外,同時 Scrapyd 還提供了較豐富的 API:

  • 服務中爬蟲狀態查詢 curl http://localhost:6800/daemonstatus.json
  • 取消爬蟲 curl http://localhost:6800/cancel.json -d project=projectName -d job=jobId
  • 展現項目 curl http://localhost:6800/listprojects.json
  • 刪除項目 curl http://localhost:6800/delproject.json -d project=projectName
  • 展現爬蟲 curl http://localhost:6800/listspiders.json?project=projectName
  • 獲取項目全部版本號 curl http://localhost:6800/listversions.json?project=projectName
  • 刪除項目版本號 curl http://localhost:6800/delversion.json -d project=projectName -d version=versionName

更多詳情 https://scrapyd.readthedocs.io/en/stable/api.html

總結

本文篇幅有限,剖析過程當中不能面面俱到,有些網站的反爬比較棘手的,只要咱們一一分析,都能找到破解的辦法,還有眼睛看到的數據並不必定是你拿到的數據,好比有些網站的html渲染都是動態的,就須要咱們去處理好這些信息。當你走進crawler的世界,你就會發現,其實挺有意思的。最後,但願你們不要面向監獄爬蟲,數據千萬條,遵紀守法第一條。

我的博客: https://ytao.top

個人公衆號 ytao

個人公衆號

相關文章
相關標籤/搜索