Python3網絡爬蟲快速入門實戰解析

以下內容轉載自https://blog.csdn.net/c406495762/article/details/78123502
【本文爲轉載的文章,非原創,以下內容來自轉載的鏈接】

個人網站:http://cuijiahua.com。					
https://blog.csdn.net/c406495762/article/details/78123502
轉載請註明作者和出處: http://blog.csdn.net/c406495762

Github代碼獲取:https://github.com/Jack-Cherish/python-spider

Python版本: Python3.x

運行平臺: Windows

IDE: Sublime text3

PS:本文爲Gitchat線上分享文章,該文章發佈時間爲2017年09月19日。活動地址:

http://gitbook.cn/m/mazi/activity/59b09bbf015c905277c2cc09


更多教程,請查看:https://cuijiahua.com/blog/spider/

一 前言

**強烈建議:**請在電腦的陪同下,閱讀本文。本文以實戰爲主,閱讀過程如稍有不適,還望多加練習。
本文的實戰內容有:

  • 網絡小說下載(靜態網站)
  • 優美壁紙下載(動態網站)
  • 愛奇藝VIP視頻下載

二 網絡爬蟲簡介

網絡爬蟲,也叫網絡蜘蛛(Web Spider)。它根據網頁地址(URL)爬取網頁內容,而網頁地址(URL)就是我們在瀏覽器中輸入的網站鏈接。比如:https://www.baidu.com/,它就是一個URL。

在講解爬蟲內容之前,我們需要先學習一項寫爬蟲的必備技能:審查元素(如果已掌握,可跳過此部分內容)。

1 審查元素

在瀏覽器的地址欄輸入URL地址,在網頁處右鍵單擊,找到檢查。(不同瀏覽器的叫法不同,Chrome瀏覽器叫做檢查,Firefox瀏覽器叫做查看元素,但是功能都是相同的)

我們可以看到,右側出現了一大推代碼,這些代碼就叫做HTML。什麼是HTML?舉個容易理解的例子:我們的基因決定了我們的原始容貌,服務器返回的HTML決定了網站的原始容貌。

爲啥說是原始容貌呢?因爲人可以整容啊!扎心了,有木有?那網站也可以"整容"嗎?可以!請看下圖:

我能有這麼多錢嗎?顯然不可能。我是怎麼給網站"整容"的呢?就是通過修改服務器返回的HTML信息。我們每個人都是"整容大師",可以修改頁面信息。我們在頁面的哪個位置點擊審查元素,瀏覽器就會爲我們定位到相應的HTML位置,進而就可以在本地更改HTML信息。

**再舉個小例子:**我們都知道,使用瀏覽器"記住密碼"的功能,密碼會變成一堆小黑點,是不可見的。可以讓密碼顯示出來嗎?可以,只需給頁面"動個小手術"!以淘寶爲例,在輸入密碼框處右鍵,點擊檢查。

可以看到,瀏覽器爲我們自動定位到了相應的HTML位置。將下圖中的password屬性值改爲text屬性值(直接在右側代碼處修改):

我們讓瀏覽器記住的密碼就這樣顯現出來了:

說這麼多,什麼意思呢?**瀏覽器就是作爲客戶端從服務器端獲取信息,然後將信息解析,並展示給我們的。**我們可以在本地修改HTML信息,爲網頁"整容",但是我們修改的信息不會回傳到服務器,服務器存儲的HTML信息不會改變。刷新一下界面,頁面還會回到原本的樣子。這就跟人整容一樣,我們能改變一些表面的東西,但是不能改變我們的基因。

2 簡單實例

網絡爬蟲的第一步就是根據URL,獲取網頁的HTML信息。在Python3中,可以使用urllib.requestrequests進行網頁爬取。

  • urllib庫是python內置的,無需我們額外安裝,只要安裝了Python就可以使用這個庫。
  • requests庫是第三方庫,需要我們自己安裝。

requests庫強大好用,所以本文使用requests庫獲取網頁的HTML信息。requests庫的github地址:https://github.com/requests/requests

(1) requests安裝

在cmd中,使用如下指令安裝requests:

pip install requests
  • 1

或者:

easy_install requests
  • 1

(2) 簡單實例

requests庫的基礎方法如下:

官方中文教程地址:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

requests庫的開發者爲我們提供了詳細的中文教程,查詢起來很方便。本文不會對其所有內容進行講解,摘取其部分使用到的內容,進行實戰說明。

首先,讓我們看下requests.get()方法,它用於向服務器發起GET請求,不瞭解GET請求沒有關係。我們可以這樣理解:get的中文意思是得到、抓住,那這個requests.get()方法就是從服務器得到、抓住數據,也就是獲取數據。讓我們看一個例子(以 www.gitbook.cn爲例)來加深理解:

# -*- coding:UTF-8 -*-
import requests

if name == ‘main’:
target = ‘http://gitbook.cn/
req = requests.get(url=target)
print(req.text)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

requests.get()方法必須設置的一個參數就是url,因爲我們得告訴GET請求,我們的目標是誰,我們要獲取誰的信息。運行程序看下結果:

左側是我們程序獲得的結果,右側是我們在www.gitbook.cn網站審查元素獲得的信息。我們可以看到,我們已經順利獲得了該網頁的HTML信息。這就是一個最簡單的爬蟲實例,可能你會問,我只是爬取了這個網頁的HTML信息,有什麼用呢?客官稍安勿躁,接下來進入我們的實戰正文。


三 爬蟲實戰

1 小說下載

(1) 實戰背景

小說網站-筆趣看:URL:http://www.biqukan.com/

筆趣看是一個盜版小說網站,這裏有很多起點中文網的小說,該網站小說的更新速度稍滯後於起點中文網正版小說的更新速度。並且該網站只支持在線瀏覽,不支持小說打包下載。因此,本次實戰就是從該網站爬取並保存一本名爲《一念永恆》的小說,該小說是耳根正在連載中的一部玄幻小說。PS:本實例僅爲交流學習,支持耳根大大,請上起點中文網訂閱。

(2) 小試牛刀

我們先看下《一念永恆》小說的第一章內容,URL:http://www.biqukan.com/1_1094/5403177.html

我們先用已經學到的知識獲取HTML信息試一試,編寫代碼如下:

# -*- coding:UTF-8 -*-
import requests

if name == ‘main’:
target = ‘http://www.biqukan.com/1_1094/5403177.html
req = requests.get(url=target)
print(req.text)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

運行代碼,可以看到如下結果:

可以看到,我們很輕鬆地獲取了HTML信息。但是,很顯然,很多信息是我們不想看到的,我們只想獲得如右側所示的正文內容,我們不關心div、br這些html標籤。如何把正文內容從這些衆多的html標籤中提取出來呢?這就是本次實戰的主要內容。

###(3)Beautiful Soup

**爬蟲的第一步,獲取整個網頁的HTML信息,我們已經完成。接下來就是爬蟲的第二步,解析HTML信息,提取我們感興趣的內容。**對於本小節的實戰,我們感興趣的內容就是文章的正文。提取的方法有很多,例如使用正則表達式、Xpath、Beautiful Soup等。對於初學者而言,最容易理解,並且使用簡單的方法就是使用Beautiful Soup提取感興趣內容。

Beautiful Soup的安裝方法和requests一樣,使用如下指令安裝(也是二選一):

  • pip install beautifulsoup4
  • easy_install beautifulsoup4

一個強大的第三方庫,都會有一個詳細的官方文檔。我們很幸運,Beautiful Soup也是有中文的官方文檔。

URL:http://beautifulsoup.readthedocs.io/zh_CN/latest/

同理,我會根據實戰需求,講解Beautiful Soup庫的部分使用方法,更詳細的內容,請查看官方文檔。

現在,我們使用已經掌握的審查元素方法,查看一下我們的目標頁面,你會看到如下內容:

不難發現,文章的所有內容都放在了一個名爲div的“東西下面”,這個"東西"就是html標籤。HTML標籤是HTML語言中最基本的單位,HTML標籤是HTML最重要的組成部分。不理解,沒關係,我們再舉個簡單的例子:

一個女人的包包裏,會有很多東西,她們會根據自己的習慣將自己的東西進行分類放好。鏡子和口紅這些會經常用到的東西,會歸放到容易拿到的外側口袋裏。那些不經常用到,需要注意安全存放的證件會放到不容易拿到的裏側口袋裏。

html標籤就像一個個“口袋”,每個“口袋”都有自己的特定功能,負責存放不同的內容。顯然,上述例子中的div標籤下存放了我們關心的正文內容。這個div標籤是這樣的:

<div id="content", class="showtxt">
  • 1

細心的朋友可能已經發現,除了div字樣外,還有id和class。id和class就是div標籤的屬性,content和showtxt是屬性值,一個屬性對應一個屬性值。這東西有什麼用?它是用來區分不同的div標籤的,因爲div標籤可以有很多,我們怎麼加以區分不同的div標籤呢?就是通過不同的屬性值。

仔細觀察目標網站一番,我們會發現這樣一個事實:class屬性爲showtxt的div標籤,獨一份!這個標籤裏面存放的內容,是我們關心的正文部分。

知道這個信息,我們就可以使用Beautiful Soup提取我們想要的內容了,編寫代碼如下:

# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
     target = 'http://www.biqukan.com/1_1094/5403177.html'
     req = requests.get(url = target)
     html = req.text
     bf = BeautifulSoup(html)
     texts = bf.find_all('div', class_ = 'showtxt') print(texts)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在解析html之前,我們需要創建一個Beautiful Soup對象。BeautifulSoup函數裏的參數就是我們已經獲得的html信息。然後我們使用find_all方法,獲得html信息中所有class屬性爲showtxt的div標籤。find_all方法的第一個參數是獲取的標籤名,第二個參數class_是標籤的屬性,爲什麼不是class,而帶了一個下劃線呢?因爲python中class是關鍵字,爲了防止衝突,這裏使用class_表示標籤的class屬性,class_後面跟着的showtxt就是屬性值了。看下我們要匹配的標籤格式:

<div id="content", class="showtxt">
  • 1

這樣對應的看一下,是不是就懂了?可能有人會問了,爲什麼不是find_all(‘div’, id = ‘content’, class_ = ‘showtxt’)?這樣其實也是可以的,屬性是作爲查詢時候的約束條件,添加一個class_='showtxt’條件,我們就已經能夠準確匹配到我們想要的標籤了,所以我們就不必再添加id這個屬性了。運行代碼查看我們匹配的結果:

我們可以看到,我們已經順利匹配到我們關心的正文內容,但是還有一些我們不想要的東西。比如div標籤名,br標籤,以及各種空格。怎麼去除這些東西呢?我們繼續編寫代碼:

# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
     target = 'http://www.biqukan.com/1_1094/5403177.html'
     req = requests.get(url = target) html = req.text
     bf = BeautifulSoup(html)
     texts = bf.find_all('div', class_ = 'showtxt')
     print(texts[0].text.replace('\xa0'*8,'\n\n'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

find_all匹配的返回的結果是一個列表。提取匹配結果後,使用text屬性,提取文本內容,濾除br標籤。隨後使用replace方法,剔除空格,替換爲回車進行分段。 在html中是用來表示空格的。replace(’\xa0’*8,’\n\n’)就是去掉下圖的八個空格符號,並用回車代替:

程序運行結果如下:

可以看到,我們很自然的匹配到了所有正文內容,並進行了分段。我們已經順利獲得了一個章節的內容,要想下載正本小說,我們就要獲取每個章節的鏈接。我們先分析下小說目錄:

URL:http://www.biqukan.com/1_1094/

通過審查元素,我們發現可以發現,這些章節都存放在了class屬性爲listmain的div標籤下,選取部分html代碼如下:

<div class="listmain">
<dl>
<dt>《一念永恆》最新章節列表</dt>
<dd><a href="/1_1094/15932394.html">第1027章 第十道門</a></dd>
<dd><a href="/1_1094/15923072.html">第1026章 絕倫道法!</a></dd>
<dd><a href="/1_1094/15921862.html">第1025章 長生燈!</a></dd>
<dd><a href="/1_1094/15918591.html">第1024章 一目晶淵</a></dd>
<dd><a href="/1_1094/15906236.html">第1023章 通天道門</a></dd>
<dd><a href="/1_1094/15903775.html">第1022章 四大凶獸!</a></dd>
<dd><a href="/1_1094/15890427.html">第1021章 鱷首!</a></dd>
<dd><a href="/1_1094/15886627.html">第1020章 一觸即發!</a></dd>
<dd><a href="/1_1094/15875306.html">第1019章 魁祖的氣息!</a></dd>
<dd><a href="/1_1094/15871572.html">第1018章 絕望的魁皇城</a></dd>
<dd><a href="/1_1094/15859514.html">第1017章 我還是恨你!</a></dd>
<dd><a href="/1_1094/15856137.html">第1016章 從來沒有世界之門!</a></dd>
<dt>《一念永恆》正文卷</dt> <dd><a href="/1_1094/5386269.html">外傳1 柯父。</a></dd>
<dd><a href="/1_1094/5386270.html">外傳2 楚玉嫣。</a></dd> <dd><a href="/1_1094/5386271.html">外傳3 鸚鵡與皮凍。</a></dd>
<dd><a href="/1_1094/5403177.html">第一章 他叫白小純</a></dd> <dd><a href="/1_1094/5428081.html">第二章 火竈房</a></dd>
<dd><a href="/1_1094/5433843.html">第三章 六句真言</a></dd> <dd><a href="/1_1094/5447905.html">第四章 煉靈</a></dd>
</dl>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在分析之前,讓我們先介紹一個概念:父節點、子節點、孫節點。<div></div>限定了<div>標籤的開始和結束的位置,他們是成對出現的,有開始位置,就有結束位置。我們可以看到,在<div>標籤包含<dl>標籤,那這個<dl>標籤就是<div>標籤的子節點,<dl>標籤又包含<dt>標籤和<dd>標籤,那麼<dt>標籤和<dd>標籤就是<div>標籤的孫節點。有點繞?那你記住這句話:誰包含誰,誰就是誰兒子!

**他們之間的關係都是相對的。**比如對於<dd>標籤,它的子節點是<a>標籤,它的父節點是<dl>標籤。這跟我們人是一樣的,上有老下有小。

看到這裏可能有人會問,這有好多<dd>標籤和<a>標籤啊!不同的<dd>標籤,它們是什麼關係啊?顯然,兄弟姐妹嘍!我們稱它們爲兄弟結點。
好了,概念明確清楚,接下來,讓我們分析一下問題。我們看到每個章節的名字存放在了<a>標籤裏面。<a>標籤還有一個href屬性。這裏就不得不提一下<a>標籤的定義了,<a>標籤定義了一個超鏈接,用於從一張頁面鏈接到另一張頁面。<a> 標籤最重要的屬性是 href 屬性,它指示鏈接的目標。

我們將之前獲得的第一章節的URL和<a> 標籤對比看一下:

http://www.biqukan.com/1_1094/5403177.html
<a href="/1_1094/5403177.html">第一章 他叫白小純</a>
  • 1
  • 2

不難發現,<a> 標籤中href屬性存放的屬性值/1_1094/5403177.html是章節URLhttp://www.biqukan.com/1_1094/5403177.html的後半部分。其他章節也是如此!那這樣,我們就可以根據<a>標籤的href屬性值獲得每個章節的鏈接和名稱了。

總結一下:小說每章的鏈接放在了class屬性爲listmain的<div>標籤下的<a>標籤中。鏈接具體位置放在html->body->div->dl->dd->a的href屬性中。先匹配class屬性爲listmain的<div>標籤,再匹配<a>標籤。編寫代碼如下:

# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
     target = 'http://www.biqukan.com/1_1094/'
     req = requests.get(url = target)
     html = req.text
     div_bf = BeautifulSoup(html)
     div = div_bf.find_all('div', class_ = 'listmain')
     print(div[0])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

還是使用find_all方法,運行結果如下:

很順利,接下來再匹配每一個<a>標籤,並提取章節名和章節文章。如果我們使用Beautiful Soup匹配到了下面這個<a>標籤,如何提取它的href屬性和<a>標籤裏存放的章節名呢?

<a href="/1_1094/5403177.html">第一章 他叫白小純</a>
  • 1

方法很簡單,對Beautiful Soup返回的匹配結果a,使用a.get(‘href’)方法就能獲取href的屬性值,使用a.string就能獲取章節名,編寫代碼如下:

# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
     server = 'http://www.biqukan.com/'
     target = 'http://www.biqukan.com/1_1094/'
     req = requests.get(url = target) html = req.text
     div_bf = BeautifulSoup(html)
     div = div_bf.find_all('div', class_ = 'listmain')
     a_bf = BeautifulSoup(str(div[0]))
     a = a_bf.find_all('a')
     for each in a:
          print(each.string, server + each.get('href'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

因爲find_all返回的是一個列表,裏邊存放了很多的<a>標籤,所以使用for循環遍歷每個<a>標籤並打印出來,運行結果如下。

最上面匹配的一千多章的內容是最新更新的12章節的鏈接。這12章內容會和下面的重複,所以我們要濾除,除此之外,還有那3個外傳,我們也不想要。這些都簡單地剔除就好。

###(3)整合代碼

每個章節的鏈接、章節名、章節內容都有了。接下來就是整合代碼,將獲得內容寫入文本文件存儲就好了。編寫代碼如下:

# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests, sys

“”"
類說明:下載《筆趣看》網小說《一念永恆》
Parameters:

Returns:

Modify:
2017-09-13
“”"
class downloader(object):

def __init__(self):
    self.server = 'http://www.biqukan.com/'
    self.target = 'http://www.biqukan.com/1_1094/'
    self.names = []            #存放章節名
    self.urls = []            #存放章節鏈接
    self.nums = 0            #章節數

"""
函數說明:獲取下載鏈接
Parameters:
    無
Returns:
    無
Modify:
    2017-09-13
"""
def get_download_url(self):
    req = requests.get(url = self.target)
    html = req.text
    div_bf = BeautifulSoup(html)
    div = div_bf.find_all('div', class_ = 'listmain')
    a_bf = BeautifulSoup(str(div[0]))
    a = a_bf.find_all('a')
    self.nums = len(a[15:])                                #剔除不必要的章節,並統計章節數
    for each in a[15:]:
        self.names.append(each.string)
        self.urls.append(self.server + each.get('href'))

"""
函數說明:獲取章節內容
Parameters:
    target - 下載連接(string)
Returns:
    texts - 章節內容(string)
Modify:
    2017-09-13
"""
def get_contents(self, target):
    req = requests.get(url = target)
    html = req.text
    bf = BeautifulSoup(html)
    texts = bf.find_all('div', class_ = 'showtxt')
    texts = texts[0].text.replace('\xa0'*8,'\n\n')
    return texts

"""
函數說明:將爬取的文章內容寫入文件
Parameters:
    name - 章節名稱(string)
    path - 當前路徑下,小說保存名稱(string)
    text - 章節內容(string)
Returns:
    無
Modify:
    2017-09-13
"""
def writer(self, name, path, text):
    write_flag = True
    with open(path, 'a', encoding='utf-8') as f:
        f.write(name + '\n')
        f.writelines(text)
        f.write('\n\n')

if name == “main”:
dl = downloader()
dl.get_download_url()
print(’《一年永恆》開始下載:’)
for i in range(dl.nums):
dl.writer(dl.names[i], ‘一念永恆.txt’, dl.get_contents(dl.urls[i]))
sys.stdout.write(" 已下載:%.3f%%" % float(i/dl.nums) + ‘\r’)
sys.stdout.flush()
print(’《一年永恆》下載完成’)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

很簡單的程序,單進程跑,沒有開進程池。下載速度略慢,喝杯茶休息休息吧。代碼運行效果如下圖所示:

2 優美壁紙下載

###(1)實戰背景

已經會爬取文字了,是不是感覺爬蟲還是蠻好玩的呢?接下來,讓我們進行一個進階實戰,瞭解一下反爬蟲。

URL:https://unsplash.com/

看一看這些優美的壁紙,這個網站的名字叫做Unsplash,免費高清壁紙分享網是一個堅持每天分享高清的攝影圖片的站點,每天更新一張高質量的圖片素材,全是生活中的景象作品,清新的生活氣息圖片可以作爲桌面壁紙也可以應用於各種需要的環境。

看到這麼優美的圖片,我的第一反應就是想收藏一些,作爲知乎文章的題圖再好不過了。每張圖片我都很喜歡,批量下載吧,不多爬,就下載50張好了。

###(2)實戰進階

我們已經知道了每個html標籤都有各自的功能。<a>標籤存放一下超鏈接,圖片存放在哪個標籤裏呢?html規定,圖片統統給我放到<img>標籤中!既然這樣,我們截取就Unsplash網站中的一個<img>標籤,分析一下:

<img alt="Snow-capped mountain slopes under blue sky" src="https://images.unsplash.com/photo-1428509774491-cfac96e12253?dpr=1&amp;auto=compress,format&amp;fit=crop&amp;w=360&amp;h=240&amp;q=80&amp;cs=tinysrgb&amp;crop=" class="cV68d" style="width: 220px; height: 147px;">
  • 1

可以看到,<img>標籤有很多屬性,有alt、src、class、style屬性,其中src屬性存放的就是我們需要的圖片保存地址,我們根據這個地址就可以進行圖片的下載。

那麼,讓我們先捋一捋這個過程:

  • 使用requeusts獲取整個網頁的HTML信息;
  • 使用Beautiful Soup解析HTML信息,找到所有<img>標籤,提取src屬性,獲取圖片存放地址;
  • 根據圖片存放地址,下載圖片。

我們信心滿滿地按照這個思路爬取Unsplash試一試,編寫代碼如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
     target = 'https://unsplash.com/'
     req = requests.get(url=target)
     print(req.text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

按照我們的設想,我們應該能找到很多<img>標籤。但是我們發現,除了一些<script>標籤和一些看不懂的代碼之外,我們一無所獲,一個<img>標籤都沒有!跟我們在網站審查元素的結果完全不一樣,這是爲什麼?

**答案就是,這個網站的所有圖片都是動態加載的!**網站有靜態網站和動態網站之分,上一個實戰爬取的網站是靜態網站,而這個網站是動態網站,動態加載有一部分的目的就是爲了反爬蟲。

對於什麼是動態加載,你可以這樣理解:我們知道化妝術學的好,賊厲害,可以改變一個人的容貌。相應的,動態加載用的好,也賊厲害,可以改變一個網站的容貌。

動態網站使用動態加載常用的手段就是通過調用JavaScript來實現的。怎麼實現JavaScript動態加載,我們不必深究,我們只要知道,動態加載的JavaScript腳本,就像化妝術需要用的化妝品,五花八門。有粉底、口紅、睫毛膏等等,它們都有各自的用途。動態加載的JavaScript腳本也一樣,一個動態加載的網站可能使用很多JavaScript腳本,我們只要找到負責動態加載圖片的JavaScript腳本,不就找到我們需要的鏈接了嗎?

對於初學者,我們不必看懂JavaScript執行的內容是什麼,做了哪些事情,因爲我們有強大的抓包工具,它自然會幫我們分析。這個強大的抓包工具就是Fiddler:

URL:http://www.telerik.com/fiddler

PS:也可以使用瀏覽器自帶的Networks,但是我更推薦這個軟件,因爲它操作起來更高效。

安裝方法很簡單,傻瓜式安裝,一直下一步即可,對於經常使用電腦的人來說,應該沒有任何難度。

這個軟件的使用方法也很簡單,打開軟件,然後用瀏覽器打開我們的目標網站,以Unsplash爲例,抓包結果如下:

我們可以看到,上圖左側紅框處是我們的GET請求的地址,就是網站的URL,右下角是服務器返回的信息,我們可以看到,這些信息也是我們上一個程序獲得的信息。這個不是我們需要的鏈接,我們繼續往下看。

我們發現上圖所示的就是一個JavaScript請求,看右下側服務器返回的信息是一個json格式的數據。這裏面,就有我們需要的內容。我們局部放大看一下:

這是Fiddler右側的信息,上面是請求的Headers信息,包括這個Javascript的請求地 址:http://unsplash.com/napi/feeds/home,其他信息我們先不管,我們看看下面的內容。裏面有很多圖片的信息,包括圖片的id,圖片的大小,圖片的鏈接,還有下一頁的地址。這個腳本以json格式存儲傳輸的數據,json格式是一種輕量級的數據交換格式,起到封裝數據的作用,易於人閱讀和編寫,同時也易於機器解析和生成。這麼多鏈接,可以看到圖片的鏈接有很多,根據哪個鏈接下載圖片呢?先別急,讓我們繼續分析:

在這個網站,我們可以按這個按鈕進行圖片下載。我們抓包分下下這個動作,看看發送了哪些請求。

https://unsplash.com/photos/1PrQ2mHW-Fo/download?force=true
https://unsplash.com/photos/JX7nDtafBcU/download?force=true
https://unsplash.com/photos/HCVbP3zqX4k/download?force=true
  • 1
  • 2
  • 3

通過Fiddler抓包,我們發現,點擊不同圖片的下載按鈕,GET請求的地址都是不同的。但是它們很有規律,就是中間有一段代碼是不一樣的,其他地方都一樣。中間那段代碼是不是很熟悉?沒錯,它就是我們之前抓包分析得到json數據中的照片的id。我們只要解析出每個照片的id,就可以獲得圖片下載的請求地址,然後根據這個請求地址,我們就可以下載圖片了。那麼,現在的首要任務就是解析json數據了。

json格式的數據也是分層的。可以看到next_page裏存放的是下一頁的請求地址,很顯然Unsplash下一頁的內容,也是動態加載的。在photos下面的id裏,存放着圖片的id,這個就是我們需要獲得的圖片id號。

怎麼編程提取這些json數據呢?我們也是分步完成:

  • 獲取整個json數據
  • 解析json數據

編寫代碼,嘗試獲取json數據:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
     target = 'http://unsplash.com/napi/feeds/home'
     req = requests.get(url=target) print(req.text)
  • 1
  • 2
  • 3
  • 4
  • 5

很遺憾,程序報錯了,問題出在哪裏?通過錯誤信息,我們可以看到SSL認證錯誤,SSL認證是指客戶端到服務器端的認證。一個非常簡單的解決這個認證錯誤的方法就是設置requests.get()方法的verify參數。這個參數默認設置爲True,也就是執行認證。我們將其設置爲False,繞過認證不就可以了?

有想法就要嘗試,編寫代碼如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
     target = 'http://unsplash.com/napi/feeds/home'
     req = requests.get(url=target, verify=False)
     print(req.text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

認證問題解決了,又有新問題了:

可以看到,我們GET請求又失敗了,這是爲什麼?這個網站反爬蟲的手段除了動態加載,還有一個反爬蟲手段,那就是驗證Request Headers。接下來,讓我們分析下這個Requests Headers:

我截取了Fiddler的抓包信息,可以看到Requests Headers裏又很多參數,有Accept、Accept-Encoding、Accept-Language、DPR、User-Agent、Viewport-Width、accept-version、Referer、x-unsplash-client、authorization、Connection、Host。它們都是什麼意思呢?

專業的解釋能說的太多,我挑重點:

  • User-Agent:這裏面存放瀏覽器的信息。可以看到上圖的參數值,它表示我是通過Windows的Chrome瀏覽器,訪問的這個服務器。如果我們不設置這個參數,用Python程序直接發送GET請求,服務器接受到的User-Agent信息就會是一個包含python字樣的User-Agent。如果後臺設計者驗證這個User-Agent參數是否合法,不讓帶Python字樣的User-Agent訪問,這樣就起到了反爬蟲的作用。這是一個最簡單的,最常用的反爬蟲手段。

  • Referer:這個參數也可以用於反爬蟲,它表示這個請求是從哪發出的。可以看到我們通過瀏覽器訪問網站,這個請求是從https://unsplash.com/,這個地址發出的。如果後臺設計者,驗證這個參數,對於不是從這個地址跳轉過來的請求一律禁止訪問,這樣就也起到了反爬蟲的作用。

  • authorization:這個參數是基於AAA模型中的身份驗證信息允許訪問一種資源的行爲。在我們用瀏覽器訪問的時候,服務器會爲訪問者分配這個用戶ID。如果後臺設計者,驗證這個參數,對於沒有用戶ID的請求一律禁止訪問,這樣就又起到了反爬蟲的作用。

Unsplash是根據哪個參數反爬蟲的呢?根據我的測試,是authorization。我們只要通過程序手動添加這個參數,然後再發送GET請求,就可以順利訪問了。怎麼什麼設置呢?還是requests.get()方法,我們只需要添加headers參數即可。編寫代碼如下:

# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
     target = 'http://unsplash.com/napi/feeds/home'
     headers = {'authorization':'your Client-ID'}
     req = requests.get(url=target, headers=headers, verify=False)
     print(req.text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

headers參數值是通過字典傳入的。記得將上述代碼中your Client-ID換成諸位自己抓包獲得的信息。代碼運行結果如下:

皇天不負有心人,可以看到我們已經順利獲得json數據了,裏面有next_page和照片的id。接下來就是解析json數據。根據我們之前分析可知,next_page放在了json數據的最外側,照片的id放在了photos->id裏。我們使用json.load()方法解析數據,編寫代碼如下:

# -*- coding:UTF-8 -*-
import requests, json
if __name__ == '__main__':
     target = 'http://unsplash.com/napi/feeds/home'
     headers = {'authorization':'your Client-ID'}
     req = requests.get(url=target, headers=headers, verify=False)
     html = json.loads(req.text)
     next_page = html['next_page']
     print('下一頁地址:',next_page)
     for each in html['photos']:
          print('圖片ID:',each['id'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

解析json數據很簡單,跟字典操作一樣,就是字典套字典。json.load()裏面的參數是原始的json格式的數據。程序運行結果如下:

圖片的ID已經獲得了,再通過字符串處理一下,就生成了我們需要的圖片下載請求地址。根據這個地址,我們就可以下載圖片了。下載方式,使用直接寫入文件的方法。

###(3)整合代碼

每次獲取鏈接加一個1s延時,因爲人在瀏覽頁面的時候,翻頁的動作不可能太快。我們要讓我們的爬蟲儘量友好一些。

# -*- coding:UTF-8 -*-
import requests, json, time, sys
from contextlib import closing

class get_photos(object):

def __init__(self):
    self.photos_id = []
    self.download_server = 'https://unsplash.com/photos/xxx/download?force=trues'
    self.target = 'http://unsplash.com/napi/feeds/home'
    self.headers = {'authorization':'Client-ID c94869b36aa272dd62dfaeefed769d4115fb3189a9d1ec88ed457207747be626'}

"""
函數說明:獲取圖片ID
Parameters:
    無
Returns:
    無
Modify:
    2017-09-13
"""   
def get_ids(self):
    req = requests.get(url=self.target, headers=self.headers, verify=False)
    html = json.loads(req.text)
    next_page = html['next_page']
    for each in html['photos']:
        self.photos_id.append(each['id'])
    time.sleep(1)
    for i in range(5):
        req = requests.get(url=next_page, headers=self.headers, verify=False)
        html = json.loads(req.text)
        next_page = html['next_page']
        for each in html['photos']:
            self.photos_id.append(each['id'])
        time.sleep(1)


"""
函數說明:圖片下載
Parameters:
    無
Returns:
    無
Modify:
    2017-09-13
"""   
def download(self, photo_id, filename):
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36'}
    target = self.download_server.replace('xxx', photo_id)
    with closing(requests.get(url=target, stream=True, verify = False, headers = self.headers)) as r:
        with open('%d.jpg' % filename, 'ab+') as f:
            for chunk in r.iter_content(chunk_size = 1024):
                if chunk:
                    f.write(chunk)
                    f.flush()

if name == ‘main’:
gp = get_photos()
print(‘獲取圖片連接中:’)
gp.get_ids()
print(‘圖片下載中:’)
for i in range(len(gp.photos_id)):
print(’ 正在下載第%d張圖片’ % (i+1))
gp.download(gp.photos_id[i], (i+1))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

下載速度還行,有的圖片下載慢是因爲圖片太大。可以看到右側也打印了一些警報信息,這是因爲我們沒有進行SSL驗證。

學會了爬取圖片,簡單的動態加載的網站也難不倒你了。趕快試試國內的一些圖片網站吧!

3 愛奇藝VIP視頻下載

###(1)實戰背景

愛奇藝的VIP視頻只有會員能看,普通用戶只能看前6分鐘。比如加勒比海盜5:

URL:http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1

我們怎麼免費看VIP視頻呢?一個簡單的方法,就是通過旋風視頻VIP解析網站。

URL:http://api.xfsub.com/

這個網站爲我們提供了免費的視頻解析,它的通用解析方式是:

http://api.xfsub.com/index.php?url=[播放地址或視頻id]
  • 1

比如,對於繡春刀這個電影,我們只需要在瀏覽器地址欄輸入:

http://api.xfsub.com/index.php?url=http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1
  • 1

這樣,我們就可以在線觀看這些VIP視頻了:

但是這個網站只提供了在線解析視頻的功能,沒有提供下載接口,如果想把視頻下載下來,我們就可以利用網絡爬蟲進行抓包,將視頻下載下來。

###(2)實戰升級

分析方法相同,我們使用Fiddler進行抓包:

我們可以看到,有用的請求並不多,我們逐條分析。我們先看第一個請求返回的信息。

可以看到第一個請求是GET請求,沒有什麼有用的信息,繼續看下一條。

我們看到,第二條GET請求地址變了,並且在返回的信息中,我們看到,這個網頁執行了一個POST請求。POST請求是啥呢?它跟GET請求正好相反,GET是從服務器獲得數據,而POST請求是向服務器發送數據,服務器再根據POST請求的參數,返回相應的內容。這個POST請求有四個參數,分別爲time、key、url、type。記住這個有用的信息,我們在抓包結果中,找一下這個請求,看看這個POST請求做了什麼。

很顯然,這個就是我們要找的POST請求,我們可以看到POST請求的參數以及返回的json格式的數據。其中url存放的參數如下:

xfsub_api\/url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http%3A%2F%2Fwww.iqiyi.com%2Fv_19rr7qhfg0.html&type=&xml=1
  • 1

這個信息有轉義了,但是沒有關係,我們手動提取一下,變成如下形式:

xfsub_api/url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http://www.iqiyi.com/v_19rr7qhfg0.html&type=&xml=1
  • 1

我們已經知道了這個解析視頻的服務器的域名,再把域名加上:

http://api.xfsub.com/xfsub_api\url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http://www.iqiyi.com/v_19rr7qhfg0.html&type=&xml=1
  • 1

這裏面存放的是什麼東西?不會視頻解析後的地址吧?我們有瀏覽器打開這個地址看一下:

我們再打開這個視頻地址:

瞧,我們就這樣得到了這個視頻在服務器上的緩存地址。根據這個地址,我們就可以輕鬆下載視頻了。

PS:需要注意一點,這些URL地址,都是有一定時效性的,很快就會失效,因爲裏面包含時間信息。所以,各位在分析的時候,要根據自己的URL結果打開網站才能看到視頻。

接下來,我們的任務就是編程實現我們所分析的步驟,根據不同的視頻播放地址獲得視頻存放的地址。

現在梳理一下編程思路:

  • 用正則表達式匹配到key、time、url等信息。
  • 根據匹配的到信息發POST請求,獲得一個存放視頻信息的url。
  • 根據這個url獲得視頻存放的地址。
  • 根據最終的視頻地址,下載視頻。

###(3)編寫代碼

編寫代碼的時候注意一個問題,就是我們需要使用requests.session()保持我們的會話請求。簡單理解就是,在初次訪問服務器的時候,服務器會給你分配一個身份證明。我們需要拿着這個身份證去繼續訪問,如果沒有這個身份證明,服務器就不會再讓你訪問。這也就是這個服務器的反爬蟲手段,會驗證用戶的身份。

#-*- coding:UTF-8 -*-
import requests,re, json
from bs4 import BeautifulSoup

class video_downloader():
def init(self, url):
self.server = ‘http://api.xfsub.com
self.api = ‘http://api.xfsub.com/xfsub_api/?url=
self.get_url_api = ‘http://api.xfsub.com/xfsub_api/url.php
self.url = url.split(’#’)[0]
self.target = self.api + self.url
self.s = requests.session()

"""
函數說明:獲取key、time、url等參數
Parameters:
    無
Returns:
    無
Modify:
    2017-09-18
"""
def get_key(self):
    req = self.s.get(url=self.target)
    req.encoding = 'utf-8'
    self.info = json.loads(re.findall('"url.php",\ (.+),', req.text)[0])    #使用正則表達式匹配結果,將匹配的結果存入info變量中

"""
函數說明:獲取視頻地址
Parameters:
    無
Returns:
    video_url - 視頻存放地址
Modify:
    2017-09-18
"""
def get_url(self):
    data = {'time':self.info['time'],
        'key':self.info['key'],
        'url':self.info['url'],
        'type':''}
    req = self.s.post(url=self.get_url_api,data=data)
    url = self.server + json.loads(req.text)['url']
    req = self.s.get(url)
    bf = BeautifulSoup(req.text,'xml')                                        #因爲文件是xml格式的,所以要進行xml解析。
    video_url = bf.find('file').string                                        #匹配到視頻地址
    return video_url

if name == ‘main’:
url = ‘http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1
vd = video_downloader(url)
vd.get_key()
print(vd.get_url())

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

思路已經給出,希望喜歡爬蟲的人可以在運行下代碼之後,自己重頭編寫程序,因爲只有經過自己分析和測試之後,才能真正明白這些代碼的意義。上述代碼運行結果如下:

我們已經順利獲得了mp4這個視頻文件地址。根據視頻地址,使用urllib.request.urlretrieve()即可將視頻下載下來。編寫代碼如下:

#-*- coding:UTF-8 -*-
import requests,re, json, sys
from bs4 import BeautifulSoup
from urllib import request

class video_downloader():
def init(self, url):
self.server = ‘http://api.xfsub.com
self.api = ‘http://api.xfsub.com/xfsub_api/?url=
self.get_url_api = ‘http://api.xfsub.com/xfsub_api/url.php
self.url = url.split(’#’)[0]
self.target = self.api + self.url
self.s = requests.session()

"""
函數說明:獲取key、time、url等參數
Parameters:
    無
Returns:
    無
Modify:
    2017-09-18
"""
def get_key(self):
    req = self.s.get(url=self.target)
    req.encoding = 'utf-8'
    self.info = json.loads(re.findall('"url.php",\ (.+),', req.text)[0])    #使用正則表達式匹配結果,將匹配的結果存入info變量中

"""
函數說明:獲取視頻地址
Parameters:
    無
Returns:
    video_url - 視頻存放地址
Modify:
    2017-09-18
"""
def get_url(self):
    data = {'time':self.info['time'],
        'key':self.info['key'],
        'url':self.info['url'],
        'type':''}
    req = self.s.post(url=self.get_url_api,data=data)
    url = self.server + json.loads(req.text)['url']
    req = self.s.get(url)
    bf = BeautifulSoup(req.text,'xml')                                        #因爲文件是xml格式的,所以要進行xml解析。
    video_url = bf.find('file').string                                        #匹配到視頻地址
    return video_url

"""
函數說明:回調函數,打印下載進度
Parameters:
    a b c - 返回信息
Returns:
    無
Modify:
    2017-09-18
"""
def Schedule(self, a, b, c):
    per = 100.0*a*b/c
    if per &gt; 100 :
        per = 1
    sys.stdout.write("  " + "%.2f%% 已經下載的大小:%ld 文件大小:%ld" % (per,a*b,c) + '\r')
    sys.stdout.flush()

"""
函數說明:視頻下載
Parameters:
    url - 視頻地址
    filename - 視頻名字
Returns:
    無
Modify:
    2017-09-18
"""
def video_download(self, url, filename):
    request.urlretrieve(url=url,filename=filename,reporthook=self.Schedule)

if name == ‘main’:
url = ‘http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1
vd = video_downloader(url)
filename = ‘加勒比海盜5’
print(’%s下載中:’ % filename)
vd.get_key()
video_url = vd.get_url()
print(’ 獲取地址成功:%s’ % video_url)
vd.video_download(video_url, filename+’.mp4’)
print(’\n下載完成!’)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

urlretrieve()有三個參數,第一個url參數是視頻存放的地址,第二個參數filename是保存的文件名,最後一個是回調函數,它方便我們查看下載進度。代碼量不大,很簡單,主要在於分析過程。代碼運行結果如下:

下載速度挺快的,幾分鐘視頻下載好了。

對於這個程序,感興趣的朋友可以進行擴展一下,設計出一個小軟件,根據用戶提供的url,提供PC在線觀看、手機在線觀看、視頻下載等功能。

四 總結

  • 本次Chat講解的實戰內容,均僅用於學習交流,請勿用於任何商業用途!
  • 爬蟲時效性低,同樣的思路過了一個月,甚至一週可能無法使用,但是爬取思路都是如此,完全可以自行分析。
  • 本次實戰代碼,均已上傳我的Github,歡迎Follow、Star:https://github.com/Jack-Cherish/python-spider
  • 如有問題,請留言。如有錯誤,還望指正,謝謝!
        </div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-df60374684.css" rel="stylesheet">
            </div>@[TOC](這裏寫自定義目錄標題)

歡迎使用Markdown編輯器

你好! 這是你第一次使用 Markdown編輯器 所展示的歡迎頁。如果你想學習如何使用Markdown編輯器, 可以仔細閱讀這篇文章,瞭解一下Markdown的基本語法知識。

新的改變

我們對Markdown編輯器進行了一些功能拓展與語法支持,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫博客:

  1. 全新的界面設計 ,將會帶來全新的寫作體驗;
  2. 在創作中心設置你喜愛的代碼高亮樣式,Markdown 將代碼片顯示選擇的高亮樣式 進行展示;
  3. 增加了 圖片拖拽 功能,你可以將本地的圖片直接拖拽到編輯區域直接展示;
  4. 全新的 KaTeX數學公式 語法;
  5. 增加了支持甘特圖的mermaid語法1 功能;
  6. 增加了 多屏幕編輯 Markdown文章功能;
  7. 增加了 焦點寫作模式、預覽模式、簡潔寫作模式、左右區域同步滾輪設置 等功能,功能按鈕位於編輯區域與預覽區域中間;
  8. 增加了 檢查列表 功能。

功能快捷鍵

撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
檢查列表:Ctrl/Command + Shift + C
插入代碼:Ctrl/Command + Shift + K
插入鏈接:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G

合理的創建標題,有助於目錄的生成

直接輸入1次#,並按下space後,將生成1級標題。
輸入2次#,並按下space後,將生成2級標題。
以此類推,我們支持6級標題。有助於使用TOC語法後生成一個完美的目錄。

如何改變文本的樣式

強調文本 強調文本

加粗文本 加粗文本

標記文本

刪除文本

引用文本

H2O is是液體。

210 運算結果是 1024.

插入鏈接與圖片

鏈接: link.

圖片: Alt

帶尺寸的圖片: Alt

居中的圖片: Alt

居中並且帶尺寸的圖片: Alt

當然,我們爲了讓用戶更加便捷,我們增加了圖片拖拽功能。

如何插入一段漂亮的代碼片

博客設置頁面,選擇一款你喜歡的代碼片高亮樣式,下面展示同樣高亮的 代碼片.

// An highlighted block
var foo = 'bar';

生成一個適合你的列表

  • 項目
    • 項目
      • 項目
  1. 項目1
  2. 項目2
  3. 項目3
  • 計劃任務
  • 完成任務

創建一個表格

一個簡單的表格是這麼創建的:

項目 Value
電腦 $1600
手機 $12
導管 $1

設定內容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants將ASCII標點字符轉換爲“智能”印刷標點HTML實體。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

創建一個自定義列表

Markdown
Text-to-HTML conversion tool
Authors
John
Luke

如何創建一個註腳

一個具有註腳的文本。2

註釋也是必不可少的

Markdown將文本轉換爲 HTML

KaTeX數學公式

您可以使用渲染LaTeX數學表達式 KaTeX:

Gamma公式展示 Γ(n)=(n1)!nN\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通過歐拉積分

Γ(z)=0tz1etdt&ThinSpace;. \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

你可以找到更多關於的信息 LaTeX 數學表達式here.

新的甘特圖功能,豐富你的文章

Mon 06Mon 13Mon 20已完成 進行中 計劃一 計劃二 現有任務Adding GANTT diagram functionality to mermaid
  • 關於 甘特圖 語法,參考 這兒,

UML 圖表

可以使用UML圖表進行渲染。 Mermaid. 例如下面產生的一個序列圖::

張三李四王五你好!李四, 最近怎麼樣?你最近怎麼樣,王五?我很好,謝謝!我很好,謝謝!李四想了很長時間,文字太長了不適合放在一行.打量着王五...很好... 王五, 你怎麼樣?張三李四王五

這將產生一個流程圖。:

鏈接
長方形
圓角長方形
菱形
  • 關於 Mermaid 語法,參考 這兒,

FLowchart流程圖

我們依舊會支持flowchart的流程圖:

Created with Raphaël 2.2.0開始我的操作確認?結束yesno
  • 關於 Flowchart流程圖 語法,參考 這兒.

導出與導入

導出

如果你想嘗試使用此編輯器, 你可以在此篇文章任意編輯。當你完成了一篇文章的寫作, 在上方工具欄找到 文章導出 ,生成一個.md文件或者.html文件進行本地保存。

導入

如果你想加載一篇你寫過的.md文件或者.html文件,在上方工具欄可以選擇導入功能進行對應擴展名的文件導入,
繼續你的創作。


  1. mermaid語法說明 ↩︎

  2. 註腳的解釋 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章