使用Django框架開發(fā)一個(gè)網(wǎng)站

0 - 重要

有了上一篇文章中對框架的理解蟀拷,現(xiàn)在來講一下Django具體的打開方式,最好的方法自然是依附于一個(gè)項(xiàng)目允粤。

本文主要是基于Django 博客開發(fā)入門教程做的二次開發(fā)崭倘,因此,你可能需要先完整的做一遍這個(gè)教程维哈,再繼續(xù)讀下去绳姨。

我是先照著教程做了一個(gè)一模一樣的博客,因?yàn)檎娴氖且荒R粯拥睦樱跃筒环懦鰜砹似W龅倪^程中也閱讀了Django的官方文檔,為了確保我對Django的理解都是正確的购撼,以及有些地方對于這個(gè)博客我也有點(diǎn)自己的想法跪削,于是我又做了個(gè)類似的網(wǎng)站。我所作的改動(dòng)我會(huì)一一列舉出來迂求。

我做了個(gè)什么碾盐?

我的想法是做一個(gè)內(nèi)容展示的平臺(tái),主要是用來展示各種爬蟲抓取到的內(nèi)容揩局,具體的文字采用MD格式毫玖。雖然我很想直接做個(gè)通用平臺(tái),但是時(shí)間有限凌盯,而且也沒找到什么好看的頁面模板付枫,就先擱下了。這里我還是找了一個(gè)類博客的模板驰怎,用的內(nèi)容資源是之前爬取百度貼吧時(shí)的帖子內(nèi)容阐滩。

當(dāng)前的測試內(nèi)容是從百度貼吧里抓取到的10個(gè)帖子,分別來源于來個(gè)dota2復(fù)仇者聯(lián)盟吧县忌。在項(xiàng)目里掂榔,每個(gè)貼吧對應(yīng)一個(gè)Category继效,每個(gè)帖子對應(yīng)一個(gè)Sticker

1 - 改動(dòng)的地方

關(guān)于設(shè)計(jì)模板和模板標(biāo)簽語言

我們已經(jīng)知道在Django中装获,一個(gè)網(wǎng)頁會(huì)由兩部分組成:靜態(tài)文件(js, css, img...)和HTML文檔瑞信。前者讓網(wǎng)站變得美觀,而后者則定義了網(wǎng)站的結(jié)構(gòu)和功能饱溢。Django則提供了一些方法用來動(dòng)態(tài)生成HTML文檔喧伞,這些方法被稱為標(biāo)簽,標(biāo)簽有很多種绩郎,我從兩個(gè)大括號(hào):{{ xxxxx }}說起潘鲫。

這類標(biāo)簽官方?jīng)]有命名,但說明了它返回的是被符號(hào)包含的語句的屬性值肋杖,這個(gè)值可以直接來源于某個(gè)變量溉仑,也可以來源于某個(gè)函數(shù)。大多數(shù)情況状植,我們傳入一個(gè)頁面的參數(shù)是一個(gè)模型實(shí)例(定義在models.py里)或由若干實(shí)例組成的一個(gè)QuerySet浊竟,后者則通常是由自定義標(biāo)簽返回的。又一般而言津畸,我們會(huì)對QuerySet里的對象進(jìn)行遍歷振定,所有說到底{{ xxxxx }}操作的對象是一個(gè)模型實(shí)例,因此它可以調(diào)用這個(gè)模型里所有的成員方法(模型本質(zhì)上是一個(gè)類)肉拓。

這段話怎么理解后频?舉個(gè)例子,參考base.htmlindex.html

base.html

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    .....meta contents
</head>
<body>
    <header>
        {% include "common/navigation.html" %}
    </header>

    <div class="widewrapper main">
        <div class="container">
            <div class="row">
                <div class="col-md-8 blog-main">
                    {% block main %}
                    {% endblock main %}
                </div>
                <aside class="col-md-4 blog-aside">
                    
                    <div class="aside-widget">
                        {% include "common/feature.html" %}
                    </div>

                    <div class="aside-widget">
                        {% include "common/tags.html" %}
                    </div>
                </aside>
            </div>
        </div>
    </div>

    <footer>
        {% include "common/footer.html" %}
    </footer>
    
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    <script src="{% static 'js/modernizr.js' %}"></script>

</body>
</html>
index.html

{% extends 'base.html' %}
{% load staticfiles %}
{% load customTags %}

{% block main %}
<div class="row">
    {% get_all_categories as categories_list %}
    {% for category in categories_list %}
    <div class="col-md-6 col-sm-6">
        <article class=" blog-teaser">
            <header>
                <p>
                <a href="{{ category.get_absolute_url }}">
                <img src="{% static 'images/' %}{{ category.name }}/{{ category.name }}.jpg" alt=""></p>
                <h3><a href="{{ category.get_absolute_url }}">{{ category.name }}</a></h3>
            </header>
            <hr>
        </article>
    </div>
    {% empty %}
    暫無內(nèi)容暖途!
    {% endfor %}

</div>
{% endblock main %}

當(dāng)訪問的URL為/時(shí)卑惜,會(huì)返回index.html頁面,這個(gè)頁面首先繼承了base.html(用{% extends 'base.html' %}標(biāo)簽)驻售。這意味這index.html的內(nèi)容會(huì)和base.html里的內(nèi)容一起返回給客戶端露久,base.html里會(huì)用{% block %}{% endblock %}預(yù)留位置,之后在index.html中補(bǔ)足欺栗,block也可以命名毫痕,這個(gè)不難理解。

我這里是將base.html作為最基礎(chǔ)的模板迟几,因此我想將它做的盡可能地簡潔同時(shí)易于閱讀消请,于是我將其進(jìn)一步的分割開來,剝離出了feature.html, footer.html, navigation.htmltags.html瘤旨,它們分別對應(yīng)了頁面上的一部分小頁面梯啤,通過{% include %}標(biāo)簽竖伯,index.html可以將它們都包裹進(jìn)來存哲。

回到index.html因宇,我們用{% load %}標(biāo)簽載入了兩個(gè)模塊,staticfiles定義了靜態(tài)資源的路徑祟偷,customTags則是我自定義的標(biāo)簽(如果你不知道自定義標(biāo)簽是什么察滑,回頭看看文章開始部分提到的博客)。在我的自定義標(biāo)簽里我定義了一個(gè)名為get_all_categories的方法(注意這個(gè)方法是可以帶參數(shù)的修肠,參數(shù)通過get_all_categories param1 param2 ...的方式傳入)用來獲取所有的分類贺辰,它返回的是一個(gè)QuerySet類型的變量,這個(gè)后面會(huì)說嵌施。通過{% for %}, {% empty %}{% endfor %}饲化,可以對這個(gè)set進(jìn)行遍歷,生成一系列結(jié)構(gòu)一致的HTML結(jié)構(gòu)吗伤。for標(biāo)簽是可以多層嵌套的吃靠。

另一種很有用的物件叫**過濾器 **,用管道符|表示足淆,它相當(dāng)于一種快捷的自定義標(biāo)簽巢块,用于快速的處理對象內(nèi)容,過濾器和標(biāo)簽其實(shí)是差不多的東西巧号,也可以互相轉(zhuǎn)化族奢。值得一提的是,過濾器具有管道特性丹鸿,因此它可以像這樣使用:{{ content|filter1|filter2|... }}越走。

最后還有一些沒提到但是很常用的標(biāo)簽列舉在這,僅供瀏覽:

  • {% if condition %}, {% elif condition2卜高,{% else %}{% endif %}
  • {% ifequal val1 val2 %}{% ifnotequal val1 val2 %}
    • 配合else: {% ifequal val1 val2 %}, {% else %}{% endifequal %}弥姻,ifnotequal同理。
  • {# #}注釋

都很容易理解掺涛。Django稱這些標(biāo)簽為The Django template language庭敦,同時(shí)列出了所有可以用的標(biāo)簽Built-in template tags and filters。通過使用模板可以使代碼的結(jié)構(gòu)變得清晰薪缆,通過使用標(biāo)簽秧廉,可以“動(dòng)態(tài)”生成網(wǎng)頁的內(nèi)容。

關(guān)于URL的參數(shù)傳遞

上一節(jié)中拣帽,single.html中使用的category是從自定義標(biāo)簽中的一個(gè)方法返回的疼电,我們也可以在生成頁面的時(shí)候直接給頁面?zhèn)鬟f一個(gè)內(nèi)容。

首先梳理一下一個(gè)請求的處理流程减拭,以訪問/sticker/a7f85c00424ed045316b7f8eed7e0a04/為例:

  • 瀏覽器發(fā)起請求蔽豺,URL為http://127.0.0.1:8000/sticker/a7f85c00424ed045316b7f8eed7e0a04/

  • urls.py中會(huì)匹配到url(r'^sticker/(?P<md5>[0-9a-z]+)/$', views.singleDetailView.as_view(), name='single')這一條正則表達(dá)式拧粪。這里我們抓取的是sitcker/????/????的值修陡,因?yàn)槲抑肋@是一個(gè)md5值沧侥,所以過濾的規(guī)則是所有小寫字母和數(shù)字。通過?P可以對抓取出來的內(nèi)容命名魄鸦,因此這里會(huì)得到一個(gè)類似{'md5': a7f85c00424ed045316b7f8eed7e0a04}的字典對象宴杀,有多個(gè)?P的話字典中自然也有多個(gè)值。然后這個(gè)字典會(huì)被作為參數(shù)傳入singleDetailView的一個(gè)實(shí)例對象拾因,在這個(gè)對象中旺罢,你可以使用self.kwargs['md5']訪問到這個(gè)值。在這個(gè)對象中绢记,默認(rèn)定義了三個(gè)變量:

    • model = Sticker :這個(gè)視圖(本質(zhì)上就是個(gè)類)對應(yīng)的模型扁达,此處是Sticker(在models.py中定義)。
    • template_name = 'single.html'context_object_name = 'sticker'表示這個(gè)實(shí)例要作為名為sticker的參數(shù)傳入single.html中蠢熄。
  • 如果你沒有什么特殊需求罩驻,那么singleDetailView中只要制定這三個(gè)變量即可。但是我們這里想要返回的其實(shí)是md5值為a7f85c00424ed045316b7f8eed7e0a04sticker對象护赊,因此我們要重寫get_object方法惠遏,根據(jù)md5值找到其對應(yīng)的sticker對象,此處不表骏啰。

  • 這個(gè)sticker對象會(huì)作為參數(shù)傳入single.html节吮,之后你就可以在single.html中通過類似{{ sticker.title }}{{ sticker.author }}的標(biāo)簽來生成特定的頁面了。

  • 最后自然就是將這個(gè)定制過的single.html返回給客戶端了判耕。

Django 如何處理一個(gè)請求 - 官方版

Django 如何處理一個(gè)請求: https://docs.djangoproject.com/zh-hans/2.0/topics/http/urls/#how-django-processes-a-request 寫道:

當(dāng)一個(gè)用戶請求Django 站點(diǎn)的一個(gè)頁面透绩,下面是Django 系統(tǒng)決定執(zhí)行哪個(gè)Python 代碼使用的算法:
    1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has a urlconf attribute (set by middleware), its value will be used in place of the ROOT_URLCONF setting.
    2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list of django.urls.path() and/or django.urls.re_path() instances.
    3. Django 依次匹配每個(gè)URL 模式,在與請求的URL 匹配的第一個(gè)模式停下來壁熄。
    4. Once one of the URL patterns matches, Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments:
       - 一個(gè) HttpRequest 實(shí)例帚豪。
       - If the matched URL pattern returned no named groups, then the matches from the regular expression are provided as positional arguments.
       - The keyword arguments are made up of any named parts matched by the path expression, overridden by any arguments specified in the optional kwargs argument to django.urls.path() or django.urls.re_path().
    5. If no URL pattern matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

這里我覺得第四點(diǎn)比較重要,它說在傳遞URL中的參數(shù)給視圖時(shí)草丧,有可能傳入三種不同的參數(shù):

  • 一個(gè)HTTPRequest實(shí)例狸臣,如果你足夠聰明,很容易就可以猜到這個(gè)實(shí)例的名字叫request因此昌执,在這個(gè)視圖對應(yīng)的模板文件里烛亦,可以使用類似{{ request.xxx }}來訪問HTTPRequest對象的所有方法,這有時(shí)候很有用懂拾。
  • 正則中使用()來代表需要抓取的內(nèi)容煤禽,如上文所述,我們使用?P來命名這個(gè)抓取到的內(nèi)容岖赋,但是如果不命名呢檬果?它會(huì)按照順序傳回抓取到的內(nèi)容,但是官方表示不推薦這種用法,所以我也不用选脊。這是第二種參數(shù)衷畦。
  • 第三種參數(shù),就是我們上文中所述的參數(shù)知牌,應(yīng)該也是最常用的方法。

通過傳統(tǒng)的”?”傳遞參數(shù)斤程?

那么能不能通過傳統(tǒng)的?方式傳入?yún)?shù)呢角寸?答案是肯定的,還記得傳入的那個(gè)HTTPRequest實(shí)例嗎忿墅?它有一個(gè)方法為GET扁藕,解釋為A dictionary-like object containing all given HTTP GET parameters.,如果URL是..../s.html?p1=v1疚脐,可以通過request.GET.get('p1')訪問亿柑。

至于這個(gè)參數(shù)能不能直接用正則匹配出來,我覺得是可以的棍弄,但是我沒試過望薄。

為什么用md5?

類視圖其實(shí)默認(rèn)是傳入pk參數(shù)的呼畸,也就是主鍵痕支,這是你在初始化數(shù)據(jù)庫時(shí)Django自動(dòng)生成的。一開始蛮原,我只是單純的想試試能不能傳入別的參數(shù)卧须,后來發(fā)現(xiàn)其實(shí)用md5也好,可以起到一定的反爬蟲的功效儒陨?

sticker還是sticker?

singleDetailView的內(nèi)容:

class singleDetailView(DetailView):
    model = Sticker
    template_name = 'single.html'
    context_object_name = 'sticker'

    def get_object(self, queryset=None):
        sticker = get_object_or_404(Sticker, md5=self.kwargs['md5'])
        sticker.increase_views()
        sticker.content = markdown.markdown(sticker.content,
                                    extensions=[
                                        'markdown.extensions.extra',
                                        'markdown.extensions.codehilite',
                                        'markdown.extensions.toc',
                                    ])
        return sticker

這里有兩個(gè)sticker花嘶,代碼當(dāng)然沒問題,但是改寫一些會(huì)更好理解:

class singleDetailView(DetailView):
    model = Sticker
    template_name = 'single.html'
    context_object_name = 'sticker'

    def get_object(self, queryset=None):
        obj = get_object_or_404(Sticker, md5=self.kwargs['md5'])
        obj.increase_views()
        obj.content = markdown.markdown(obj.content,
                                    extensions=[
                                        'markdown.extensions.extra',
                                        'markdown.extensions.codehilite',
                                        'markdown.extensions.toc',
                                    ])
        return obj

如上文所述蹦漠,重寫的get_object方法會(huì)返回一個(gè)Sticker對象或模型椭员,它是根據(jù)md5的值篩選出來的。這個(gè)對象obj會(huì)被賦予另一個(gè)名為sticker的變量里笛园,然后傳入single.html中拆撼,這里只是恰好使用了相同的名字。

關(guān)于帖子主題內(nèi)容的格式

網(wǎng)站的測試內(nèi)容喘沿,我是從網(wǎng)站直接抓過來的闸度,它被轉(zhuǎn)化為Markdown格式,之后再通過Markdown庫渲染成HTML格式蚜印。因此這里其實(shí)有一個(gè)HTML -> MD -> HTML的過程莺禁。私以為這不是多余的,這樣做可以過濾掉很多雜亂的HTML標(biāo)簽窄赋。如果網(wǎng)站的內(nèi)容來源是很多不同的網(wǎng)站哟冬,優(yōu)勢會(huì)更加明顯楼熄。

長URL換行問題

有時(shí)候帖子內(nèi)容中會(huì)包含一個(gè)很長的URL,這個(gè)URL不會(huì)自動(dòng)換行浩峡,因此可能會(huì)超出當(dāng)前的CSS block可岂,影響美觀。我在網(wǎng)上查到了兩種解決方法:(django問題)處理換行和空格翰灾,第二種我這沒生效缕粹。

關(guān)于ORM和數(shù)據(jù)操作

雖然Django后端使用的是sqlite3(也可以換成其他的),但是我們并不需要編寫SQL語句來操作它(但是這也是可以的)纸淮。

Django對數(shù)據(jù)操作進(jìn)行了封裝平斩,這使得我們可以通過使用Python語言直接操作數(shù)據(jù),這個(gè)過程就叫做ORM咽块,即Object-relational mapping绘面。

存入數(shù)據(jù)

這里我們已經(jīng)知道,Django中的數(shù)據(jù)模型其實(shí)就是繼承了db.models的類侈沪,在默認(rèn)文件models.py中定義揭璃。 這個(gè)類中定義的屬性即對應(yīng)了表中的一個(gè)字段,同時(shí)db.models中也定義了所有可用的字段類型亭罪。注意一對一塘辅、一對多、多對多關(guān)系的表示方法皆撩。

需要注意的是扣墩,只要你對models.py中的內(nèi)容 進(jìn)行了修改,就需要執(zhí)行:

python manage.py makemigrations
python manage.py migrate

完成數(shù)據(jù)庫的遷移扛吞,可以理解為刷新呻惕。

完成了數(shù)據(jù)庫遷移后,你就可以使用代碼直接向數(shù)據(jù)庫中寫入數(shù)據(jù)了滥比,下面會(huì)提到亚脆。

讀取數(shù)據(jù)

從數(shù)據(jù)庫中讀取數(shù)據(jù),最重要的內(nèi)容就是QuerySet 對象盲泛。值得一提的是濒持,QuerySet 對象是Lazy的(想一想生成器),這個(gè)怎么理解呢寺滚?QuerySet 對象的一個(gè)特性就是它可以進(jìn)行鏈?zhǔn)讲僮鞲逃紤]一下代碼:

r = CustomM.objects.all().filer(pk__gt=12).filter(...). ..........filert(...)

理論上你可以無限進(jìn)行鏈?zhǔn)讲僮鳎@里的trick就是雖然這行代碼被執(zhí)行了村视,但實(shí)際上這里面沒有設(shè)計(jì)到數(shù)據(jù)庫的行為考廉。那么什么時(shí)候會(huì)產(chǎn)生數(shù)據(jù)庫行為呢庸蔼?文檔上說的是`當(dāng)這個(gè)對象被evaluated的時(shí)候寄疏。哈哈,下個(gè)問題自然是對象什么時(shí)候會(huì)被evaluated呢疲扎?答案是When QuerySets are evaluated。這個(gè)文檔里列舉所有會(huì)造成數(shù)據(jù)庫行為的操作,這對寫代碼會(huì)有幫助。

在同一篇文檔里:QuerySet API reference, 里面列舉了所有QuerySet 對象的操作另伍,在我的代碼里,我其實(shí)只用到了很有限的幾個(gè):all(), order_by, filter()values()绞旅。關(guān)于這些API摆尝,我想我會(huì)另開文檔說一說,畢竟實(shí)在是太多了玻靡。

理論上,通過這些API可以完成所有的數(shù)據(jù)庫操作中贝,不管是簡單的還是復(fù)雜的SQL語句囤捻。事實(shí)上呢?

關(guān)于批量導(dǎo)入數(shù)據(jù)庫

通過合理的開發(fā)邻寿,我們當(dāng)然可以在Admin頁面中手動(dòng)添加數(shù)據(jù)蝎土。但是第一次啟動(dòng)網(wǎng)站時(shí),我們可能會(huì)需要導(dǎo)入一些初始數(shù)據(jù)绣否。Django提供了兩種方法用來向數(shù)據(jù)庫寫入數(shù)據(jù)誊涯,假如models.py中定義了一個(gè)名為Sticker的模型:

  • Sticker(name=yourname).save()
    • Sticker的參數(shù)列表需要對應(yīng)數(shù)據(jù)結(jié)構(gòu)中的字段名,save()將其生成的對象寫入數(shù)據(jù)庫中蒜撮。
  • Sticker.objects.create(title = title, author = author, content = content, category = c, md5 = md5)
    • 同樣create的參數(shù)列表需要對應(yīng)數(shù)據(jù)結(jié)構(gòu)中的字段名暴构。

在Django項(xiàng)目的根目錄下,可以執(zhí)行python manage.py shell進(jìn)入一個(gè)交互界面段磨,然后就可以使用上述方法了取逾。但是,我們更想做的應(yīng)該是在一個(gè)Python文件中執(zhí)行這些代碼苹支。

你只需要在項(xiàng)目根目錄下新建一個(gè)python文件砾隅,然后執(zhí)行它就行了。這里放上我的代碼:

# 這個(gè)一定要债蜜,不然會(huì)報(bào)錯(cuò)晴埂,但是錯(cuò)誤很明顯,容易定位寻定。
import os 
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gallery.settings") 

# django版本大于1.7時(shí)需要這兩句
import django
django.setup()

import hashlib

# 導(dǎo)入你需要寫入的兩個(gè)模型類
from sticker.models import Category, Sticker

# 第一種方法寫入數(shù)據(jù)庫
dirname = '分類1'
c = Category(name=dirname)
c.save()

file_dir = r"D:\OneDrive\Download\"

# 這里我是遍歷了file_dir中的所有文件儒洛,并依次解析它們
for file in os.listdir(file_dir): 
    with open(file_dir+'\\'+file, 'r', encoding='utf-8') as file:
        title  = file.readline().split(':')[1].strip() # 獲取第一行title值
        author = file.readline().split(':')[1].strip() # 獲取第二行author值

        content = file.read().strip() # 讀取剩余內(nèi)容,作為content狼速,即post的內(nèi)容
    
        # 根據(jù)content生成md5
        m = hashlib.md5()
        m.update(content.encode('utf-8'))
        md5 = m.hexdigest()
    
    # 第二種方法寫入數(shù)據(jù)庫
    Sticker.objects.create(title = title,
                       author = author,
                        content = content,
                        category = c,
                        md5 = md5
                        )    

關(guān)于圖片外鏈

雖然抓取到的內(nèi)容中的圖片的鏈接都是絕對路徑晶丘,但是如果直接在網(wǎng)站上使用,會(huì)被認(rèn)為是盜鏈導(dǎo)致圖片無法顯示。(怎么識(shí)別盜鏈的浅浮?)

關(guān)于這一點(diǎn)沫浆,我想到了三種解決方法:

  • 將圖片全部下載到本地,這是我目前使用的方法滚秩,也是我最不贊成使用的方法专执。這不僅使得本地文件過多,而且也不容易管理郁油。

    不過我仍然解釋下我這里是怎么做的:

    首先本股,用爬蟲去爬取每個(gè)帖子,過濾出所有的圖片桐腌,并將其下載到本地拄显,命名為tid_cnt.jpgtid是這個(gè)帖子的唯一id案站,cnt則是一個(gè)簡單的遞增值躬审。之后將所有的圖片都處理成md的語義:[圖片上傳失敗...(image-d1bc88-1532185791647)]。這樣其實(shí)已經(jīng)可以了蟆盐,如果要分細(xì)一點(diǎn)承边,可以在images后再加入不容的目錄。

    之后石挂,再將帖子刷入數(shù)據(jù)庫后博助,將下載下來的圖片都放到static/images/下面,也就是網(wǎng)站的靜態(tài)資源目錄下痹愚,這樣就可以正常訪問圖片了富岳。

  • 第二種方法就是使用云主機(jī),有一些現(xiàn)成的在線圖片外鏈生成站拯腮,最有名的就是七牛云了城瞎。

    這里我在推薦一個(gè)輕量級的站,名為SM.MS, 但是會(huì)有上傳數(shù)量限制疾瓮,不符合我的需求脖镀。這里提供一個(gè)Python版的代碼,最后的data是一個(gè)字典狼电,里面包含了生成的外鏈蜒灰。

    import requests
    import json
    
    image_path = 'mvey0559.jpg' # 要上傳的圖片路徑
    url = 'https://sm.ms/api/upload'
    files = {'smfile' : open(image_path, 'rb')}
    
    content = None
    try:
        response = requests.post(url, files=files)
    
    
        if response.status_code == requests.codes.ok:
            content = response.text
            
    except Exception as e:
        print (e)
    
    data = json.loads(content)
    print (data)
    
    
  • 最后一種方法自然就是自己部署一個(gè)圖床服務(wù)器了。目前我搜集到的信息是使用FastDFS + Python的方法:FastDFSClient_Python肩碟。但是能不能再封裝成Web形式暫時(shí)還不知道强窖,另外能不能做成只能給自己的網(wǎng)站使用的接口呢?有空我再研究研究削祈。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翅溺,一起剝皮案震驚了整個(gè)濱河市脑漫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咙崎,老刑警劉巖优幸,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異褪猛,居然都是意外死亡网杆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門伊滋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碳却,“玉大人,你說我怎么就攤上這事笑旺≈缙郑” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵筒主,是天一觀的道長关噪。 經(jīng)常有香客問我,道長物舒,這世上最難降的妖魔是什么色洞? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任戏锹,我火速辦了婚禮冠胯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锦针。我一直安慰自己荠察,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布奈搜。 她就那樣靜靜地躺著悉盆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馋吗。 梳的紋絲不亂的頭發(fā)上焕盟,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音宏粤,去河邊找鬼脚翘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绍哎,可吹牛的內(nèi)容都是我干的来农。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼崇堰,長吁一口氣:“原來是場噩夢啊……” “哼沃于!你這毒婦竟也來了涩咖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤繁莹,失蹤者是張志新(化名)和其女友劉穎檩互,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒋困,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盾似,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雪标。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片零院。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖村刨,靈堂內(nèi)的尸體忽然破棺而出告抄,到底是詐尸還是另有隱情,我是刑警寧澤嵌牺,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布打洼,位于F島的核電站,受9級特大地震影響逆粹,放射性物質(zhì)發(fā)生泄漏募疮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一僻弹、第九天 我趴在偏房一處隱蔽的房頂上張望阿浓。 院中可真熱鬧,春花似錦蹋绽、人聲如沸芭毙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽退敦。三九已至,卻和暖如春蚣抗,著一層夾襖步出監(jiān)牢的瞬間侈百,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工翰铡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钝域,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓两蟀,卻偏偏與公主長得像网梢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子赂毯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容