近在設(shè)計(jì)篩選相關(guān)頁(yè)面的時(shí)候,找來(lái)了一些參考。發(fā)現(xiàn)這種竟然有這么多不同種類的篩選設(shè)計(jì)類型,雖然以前在使用APP的時(shí)候也注意到過(guò),但是用用就忘記了。正好找機(jī)會(huì)進(jìn)行了下總結(jié)歸類,以后在碰到類似設(shè)計(jì)的時(shí)候能夠快速思考對(duì)應(yīng)哪種類型的設(shè)計(jì)比較合適。
大致我進(jìn)行了如下分類:
標(biāo)簽式篩選我們是最為常見的,比較典型的是在搜索頁(yè)面篩選中被廣泛使用。怎么運(yùn)用這里就不多說(shuō)了,大家都非常熟悉。
如下圖:
我們?cè)谌粘I铑愘?gòu)物的時(shí)候,例如購(gòu)買日用品、食物、便利商品的時(shí)候經(jīng)常會(huì)看到這種左側(cè)導(dǎo)航式篩選、這種導(dǎo)航式篩選比較適合品種類目特別多,層級(jí)分類較深的時(shí)候。
單一層級(jí)如上圖兩鮮的APP,類似這種生活便利型的的APP最為常見,多層級(jí)的我們可以看下右上圖的設(shè)計(jì)。
這種設(shè)計(jì)的好處是對(duì)于相對(duì)復(fù)雜的層級(jí)分類,能夠清晰有條理的收納。可以盡可能多的展示更多入口,尤其是對(duì)于購(gòu)物類的APP能夠增加多頻道的流量,當(dāng)然流量也可以轉(zhuǎn)換更多的交易量。
下拉式篩選分為:下拉彈窗、下拉卡片式篩選、下拉菜單加左側(cè)列表層疊式。
(1)下拉彈窗
我們可以看到上圖左一嗶哩嗶哩采用的下拉彈窗,這種樣式是篩選中比較常見的,最為普通的是單一層下拉彈窗,但這里嗶哩嗶哩運(yùn)用了層疊式的篩選形式,在設(shè)計(jì)上上面一排跟下面一排除了文字大小并沒有太大的區(qū)分,體驗(yàn)很差,再加上下拉彈窗一大堆的文字分類,密集恐懼癥有沒有。
(2)下拉卡片式篩選
那么我們?cè)賮?lái)看看京東同樣運(yùn)用了層疊式的下拉彈窗設(shè)計(jì),第一排跟第二排設(shè)計(jì)上有了明顯的區(qū)分,第二排采用了底板標(biāo)簽式樣,很好的區(qū)分了上下的層次感,另外一點(diǎn)為了進(jìn)一步加深區(qū)分,利用矩形標(biāo)簽的形狀,采用了卡片式的選項(xiàng)卡分類設(shè)計(jì)。信息雖多但每一個(gè)細(xì)節(jié)的層次感區(qū)分明顯,不失為好的設(shè)計(jì)。
(3)下拉菜單加左側(cè)列表層疊式
這種篩選形式首先采用了之前說(shuō)的列表層疊式樣式,同時(shí)它又是下拉菜單的形式。我們?cè)俅胃鷨袅▎袅ǖ脑O(shè)計(jì)進(jìn)行對(duì)比,如果像嗶哩嗶哩這種信息模塊特別多的情況,其實(shí)可以對(duì)三級(jí)菜單進(jìn)行再次歸類,結(jié)合左側(cè)列表層疊的樣式進(jìn)行設(shè)計(jì)。或是借鑒下京東的層次區(qū)分的設(shè)計(jì),展示效果會(huì)大大提升。
折疊式篩選在網(wǎng)頁(yè)端運(yùn)用的相對(duì)較多,其實(shí)在APP端用也非常好,因?yàn)檫@種形式如果第二層級(jí)分類不多,或者是第二層級(jí)信息量較少的情況下我們采用信息折疊的形式是比較好的。可以減少頁(yè)面的跳轉(zhuǎn),用戶只需要在當(dāng)前頁(yè)面獲取信息或者是在當(dāng)前頁(yè)面進(jìn)行篩選。
浮層引導(dǎo)式篩選常常用于首次進(jìn)入APP的時(shí)候,幫助用戶篩選出自己感興趣的內(nèi)容,之后方便后臺(tái)進(jìn)行數(shù)據(jù)統(tǒng)計(jì),然后根據(jù)不同用戶的喜好推送不同的內(nèi)容。這樣一勞永逸的篩選形式,避免了后期不必要的麻煩。而且全屏展示能夠提供更大的展示空間。
橫條式篩選包括:橫條標(biāo)尺型篩選、橫條進(jìn)度條型篩選
(1)橫條標(biāo)尺型篩選
上圖左一是京東金融的小白理財(cái)頁(yè)面,采用了比較新穎的標(biāo)尺進(jìn)行投資額的設(shè)定,用戶只需要左右滑動(dòng)即可,可操作性很強(qiáng),避免了用戶填寫數(shù)值的反感情緒。
(2)橫條進(jìn)度條型篩選
右上圖采用了進(jìn)度條的設(shè)計(jì),用戶拖動(dòng)滑塊即可確定數(shù)值,操作上沒有標(biāo)尺型那樣靈活,但適合用于彈窗或者是小的模塊上。
彈窗式篩選主要分為:彈窗型篩選和底部彈窗型篩選
(1)彈窗型篩選
彈窗型的篩選一般來(lái)說(shuō)還是比較少見的,通常情況下還是慎用,因?yàn)閺棿皶?huì)打斷用戶瀏覽當(dāng)前頁(yè)面,影響操作的連貫性。類似于這種情況呢,我就建議使用下拉彈窗式篩選或者右側(cè)抽屜式篩選效果會(huì)更好,也不會(huì)打斷用戶對(duì)整個(gè)頁(yè)面的預(yù)覽。
(2)底部彈窗型篩選
上右圖的底部彈窗式篩選這種方式通常用于底部菜單欄的操作二級(jí)篩選展示,這種就比用彈窗型篩選好很多,把對(duì)整個(gè)頁(yè)面的干擾降到最低。
填鴨式篩選通常用于多選情況比較多,當(dāng)然也有單選的時(shí)候,還有填寫調(diào)查問(wèn)卷或者測(cè)試題的時(shí)候。
我們可以看到上圖左的底部彈窗填鴨式篩選,右側(cè)對(duì)篩選項(xiàng)目進(jìn)行了選中的高亮型設(shè)計(jì),層次感非常好。這種模擬填鴨的形式模擬了真實(shí)的習(xí)題選擇,可視化較強(qiáng),是一種不錯(cuò)的設(shè)計(jì)形式。
我們?cè)賮?lái)看看右圖的字母選項(xiàng)卡填鴨式設(shè)計(jì),這個(gè)藥品的分類就很好,同樣類似于上面嗶哩嗶哩面臨入口模塊繁雜的情況。
一般這種精細(xì)化的選擇的目標(biāo)用戶是深度用戶,有明確目的性的。漫無(wú)目的的用戶不會(huì)去篩選這么復(fù)雜的操作。所以這里巧妙的結(jié)合運(yùn)用了字母選項(xiàng)卡的設(shè)計(jì),然后對(duì)信息入口進(jìn)行了歸類整合分隔展示,整個(gè)頁(yè)面看起來(lái)更有邏輯調(diào)理。
日期篩選分為:滾動(dòng)式和日歷式。
(1)滾動(dòng)式篩選
日期滾動(dòng)式篩選是iOS里的日期篩選特性,也是極為常見的設(shè)計(jì)形式。這種篩選形式有點(diǎn)像密碼鎖,操作趣味性強(qiáng),降低用戶填寫數(shù)字的負(fù)面情緒。但是記得在我之前工作的時(shí)候?qū)蛹?jí)采用了日期滾動(dòng)式設(shè)計(jì),在進(jìn)行安卓后期的調(diào)整的時(shí)候發(fā)現(xiàn)開發(fā)告知我安卓沒辦法做出具有景深的滾動(dòng)效果。那么視覺效果就大打折扣了。
實(shí)際上安卓的設(shè)計(jì)規(guī)范Material Design采用的是菜單原地展開,蓋住當(dāng)前選項(xiàng),當(dāng)前選項(xiàng)成為菜單的第一項(xiàng)的設(shè)計(jì)形式。并非iOS的滾動(dòng)式篩選,如下圖所示。
所以我們運(yùn)用滾動(dòng)式設(shè)計(jì)形式的時(shí)候,記得要考慮iOS跟安卓的平臺(tái)差異性。
(2)日歷篩選
日歷篩選是另一種日期篩選形式,這種形式適合運(yùn)用在購(gòu)買機(jī)票火車票,或者是期刊專題類設(shè)計(jì)的頁(yè)面上。因?yàn)橛袝r(shí)候可能我們并不是很明確要選擇哪個(gè)日期,尤其是買飛機(jī)票我們要看不同日期的不同票價(jià)進(jìn)行比對(duì)。還有期刊專題我們回顧往期期刊的時(shí)候,并不會(huì)明確的記得哪個(gè)日期沒有看。這時(shí)候就需要可視化更強(qiáng)的設(shè)計(jì),日歷篩選。
右側(cè)抽屜式設(shè)計(jì)其實(shí)是比較綜合類的篩選設(shè)計(jì),通常情況下跟下拉式彈窗設(shè)計(jì)結(jié)合使用。通常展示了不同的篩選形式,例如標(biāo)簽式篩選、折疊式篩選、填鴨式篩選等等。總之當(dāng)我們需要展示不同篩選形式的時(shí)候推薦使用右側(cè)抽屜式篩選設(shè)計(jì)。
這里我們針對(duì)不同的使用場(chǎng)景總結(jié)出了十大篩選類型,分別為:標(biāo)簽式篩選、左側(cè)導(dǎo)航式篩選、下拉式篩選、折疊式篩選、浮層引導(dǎo)式篩選、橫條式篩選、彈窗式篩選、填鴨式篩選、日期篩選、右側(cè)抽屜式篩選。
相信我們?cè)谝院笤O(shè)計(jì)篩選模塊的時(shí)候不至于束手無(wú)策了,希望本篇對(duì)您有幫助!
作者:角馬X ,口袋理財(cái)U(kuò)ED設(shè)計(jì)經(jīng)理 公眾號(hào):海鹽社
本文由 @角馬X 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載
題圖來(lái)自Unsplash,基于CC0協(xié)議
eb爬取是從Web上收集和解析數(shù)據(jù)的過(guò)程。Python社區(qū)已經(jīng)開發(fā)出一些非常強(qiáng)大的web爬取工具。其中,Pandas read_html()是從html表中爬取數(shù)據(jù)的一種快速方便的方法。
在本文中,你將學(xué)習(xí)Pandas read_html()來(lái)處理以下常見問(wèn)題,并幫助你進(jìn)行web爬取。
1.從字符串讀取表
2.從URL讀取表
3.從文件讀取表
4.使用parse_dates分析日期列
5.使用converters顯式轉(zhuǎn)換類型
6.多索引、標(biāo)題和索引列
7.用match匹配表
8.使用屬性篩選表
9.使用缺失值
請(qǐng)檢查Notebook的源代碼(https://github.com/BindiChen/machine-learning/blob/master/data-analysis/024-pandas-read_html/pandas-read_html.ipynb)。
在第一個(gè)示例中,我們將從字符串中讀取HTML表。
html_string="""
<table>
<thead>
<tr>
<th>date</th>
<th>name</th>
<th>year</th>
<th>cost</th>
<th>region</th>
</tr>
</thead>
<tbody>
<tr>
<td>2020-01-01</td>
<td>Jenny</td>
<td>1998</td>
<td>0.2</td>
<td>South</td>
</tr>
<tr>
<td>2020-01-02</td>
<td>Alice</td>
<td>1992</td>
<td>-1.34</td>
<td>East</td>
</tr>
<tr>
<td>2020-01-03</td>
<td>Tomas</td>
<td>1982</td>
<td>1.00023</td>
<td>South</td>
</tr>
</tbody>
</table>
"""
要從字符串中讀取表,請(qǐng)執(zhí)行以下操作:
dfs=pd.read_html(html_string)
現(xiàn)在,我們得到的結(jié)果不是Pandas數(shù)據(jù)幀而是Python列表。如果使用type()函數(shù),可以看到:
>>> type(dfs)
list
如果要獲取表,可以使用索引訪問(wèn)它:
dfs[0]
結(jié)果看起來(lái)很棒。讓我們看看dfs[0].info()的數(shù)據(jù)類型。默認(rèn)情況下,數(shù)值列被轉(zhuǎn)換為數(shù)值類型,例如,year和cost列分別被轉(zhuǎn)換為int64和float64。
>>> df[0].info()
RangeIndex: 3 entries, 0 to 2
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 3 non-null object
1 name 3 non-null object
2 year 3 non-null int64
3 cost 3 non-null float64
4 region 3 non-null object
dtypes: float64(1), int64(1), object(3)
memory usage: 248.0+ bytes
Pandas read_html()接受URL。讓我們通過(guò)一個(gè)例子來(lái)看看這是如何工作的。
URL='https://en.wikipedia.org/wiki/London'
dfs=pd.read_html(URL)
與從字符串讀取相同,它返回一個(gè)數(shù)據(jù)幀列表。如果我們運(yùn)行l(wèi)en(dfs),我們可以從給定的URL得到31個(gè)表。
>>> print(f'Total tables: {len(dfs)}')
31
下面是dfs[6]的一個(gè)例子:
Pandas read_html()接受一個(gè)文件。讓我們通過(guò)一個(gè)例子來(lái)看看這是如何工作的。
file_path='html_string.txt'
with open(file_path, 'r') as f:
dfs=pd.read_html(f.read())
dfs[0]
注意:以下教程將從字符串中讀取數(shù)據(jù),因?yàn)殡S著時(shí)間的推移,網(wǎng)頁(yè)內(nèi)容可能變更。
日期列作為對(duì)象數(shù)據(jù)類型讀取。要正確讀取日期列,可以使用參數(shù)parse_dates指定日期列的列表。
>>> dfs=pd.read_html(html_string, parse_dates=['date'])
>>> dfs[0].info()
RangeIndex: 3 entries, 0 to 2
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 3 non-null datetime64[ns]
1 name 3 non-null object
2 year 3 non-null int64
3 cost 3 non-null float64
4 region 3 non-null object
dtypes: datetime64[ns](1), float64(1), int64(1), object(2)
memory usage: 248.0+ bytes
默認(rèn)情況下,數(shù)值列被轉(zhuǎn)換為數(shù)值類型,例如,我們看到的year和cost列。但并非所有的數(shù)字文本數(shù)據(jù)都必須是數(shù)字類型,例如,所有值都以零開頭的ID列。
ID=0001
此外,有時(shí)可能需要顯式地進(jìn)行類型轉(zhuǎn)換以確保數(shù)據(jù)類型的完整性。對(duì)于這些要求,我們可以使用參數(shù)轉(zhuǎn)換器顯式地進(jìn)行類型轉(zhuǎn)換:
dfs=pd.read_html(html_string, converters={
'ID': str,
'year': int,
'cost': float,
})
默認(rèn)情況下,位于<thead>中的<th>或<td>元素用于形成列索引,如果<thead>中包含多行,則創(chuàng)建一個(gè)多索引。
下面是一個(gè)在<thead>中包含多行的HTML表的示例。
html_string="""
<table>
<thead>
<tr>
<th colspan="5">Year 2020</th>
</tr>
<tr>
<th>date</th>
<th>name</th>
<th>year</th>
<th>cost</th>
<th>region</th>
</tr>
</thead>
<tbody>
<tr>
<td>2020-01-01</td>
<td>Jenny</td>
<td>1998</td>
<td>1.2</td>
<td>South</td>
</tr>
<tr>
<td>2020-01-02</td>
<td>Alice</td>
<td>1992</td>
<td>-1.34</td>
<td>East</td>
</tr>
</tbody>
</table>
"""
它創(chuàng)建多重索引,因?yàn)?lt;thead>中有多行。
dfs=pd.read_html(html_string)
dfs[0]
指定標(biāo)題行:
dfs=pd.read_html(html_string, header=1)
dfs[0]
指定索引列:
dfs=pd.read_html(html_string, header=1, index_col=0)
dfs[0]
參數(shù)匹配采用字符串或正則表達(dá)式。該值默認(rèn)為.+(匹配任何非空字符串),并將返回所有表。
我們通過(guò)一個(gè)例子來(lái)看看這是如何工作的。
html_string="""
<table id="report">
<caption>2020 report</caption>
<thead>
<tr>
<th>date</th>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<td>2020-01-01</td>
<td>Jenny</td>
</tr>
<tr>
<td>2020-01-02</td>
<td>Alice</td>
</tr>
</tbody>
</table>
<table>
<caption>Average income</caption>
<thead>
<tr>
<th>name</th>
<th>income</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tom</td>
<td>200</td>
</tr>
<tr>
<td>James</td>
<td>300</td>
</tr>
</tbody>
</table>
"""
要讀取包含特定文本的表:
# 標(biāo)題中的文本
dfs=pd.read_html(html_string, match='2020 report')
# 表格單元格中的文本
dfs=pd.read_html(html_string, match='James')
參數(shù)attrs接受任何有效的HTML標(biāo)記屬性的字典來(lái)篩選表。例如:
dfs=pd.read_html(html_string, attrs={'id': 'report'})
id是有效的HTML標(biāo)記屬性。
默認(rèn)情況下,所有空字符串都被視為缺失值,并作為NaN讀取。
下面是一個(gè)HTML表格的示例,其中的< td >單元格中有一些空字符串。
html_string="""
<table>
<tr>
<th>date</th>
<th>name</th>
<th>year</th>
<th>cost</th>
<th>region</th>
</tr>
<tr>
<td>2020-01-01</td>
<td>Jenny</td>
<td>1998</td>
<td>1.2</td>
<td>South</td>
</tr>
<tr>
<td>2020-01-02</td>
<td>Alice</td>
<td>1992</td>
<td></td>
<td>East</td>
</tr>
<tr>
<td>2020-01-03</td>
<td>Tomas</td>
<td>1982</td>
<td></td>
<td>South</td>
</tr>
</table>
"""
以默認(rèn)設(shè)置讀取。
dfs=pd.read_html(html_string)
dfs[0]
為了保留這些空字符串,我們可以將參數(shù)keep_default_na設(shè)置為False。
dfs=pd.read_html(html_string, keep_default_na=False)
有時(shí),對(duì)于缺少的值,你可能有其他字符表示法。如果我們知道什么類型的字符用作表中的缺失值,我們可以使用na_values參數(shù)處理它們:
dfs=pd.read_html(html_string, na_values=['?', '&'])
當(dāng)數(shù)據(jù)幀已經(jīng)創(chuàng)建好后,我們可以使用pandas replace()函數(shù)來(lái)處理這些值:
df_clean=dfs[0].replace({ "?": np.nan, "&": np.nan })
Pandas read_html()函數(shù)是一種快速方便地從html表中獲取數(shù)據(jù)的方法。
我希望本文能幫助你節(jié)省從HTML表中刪除數(shù)據(jù)的時(shí)間。建議你查看read_html()API的文檔,并了解可以做的其他事情。
謝謝你的閱讀。請(qǐng)查看Notebook的源代碼,如果你對(duì)機(jī)器學(xué)習(xí)的實(shí)際方面感興趣,請(qǐng)繼續(xù)關(guān)注:https://github.com/BindiChen/machine-learning/blob/master/data-analysis/024-pandas-read_html/pandas-read_html.ipynb。
、篩選請(qǐng)求
Show all Content-Type:顯示所有類型Content-Type的請(qǐng)求,Content-Type即為響應(yīng)結(jié)果header信息中Content-Type字段
Show only IMAGE/*:僅顯示響應(yīng)類型為圖片的請(qǐng)求
Show only HTML:僅顯示響應(yīng)類型為HTML的請(qǐng)求
Show only TEXT/CSS:僅顯示響應(yīng)類型為text/css的請(qǐng)求
Show only SCRIPTS:僅顯示響應(yīng)類型為Scripts的請(qǐng)求
Show only XML:僅顯示響應(yīng)類型為XML的請(qǐng)求
Show only JSON:僅顯示響應(yīng)類型為Json的請(qǐng)求
Hide IMAGE/*:隱藏所有響應(yīng)類型為圖片的請(qǐng)求
二、修改請(qǐng)求參數(shù)之臨時(shí)修改參數(shù)
三、斷點(diǎn)修改請(qǐng)求參數(shù)
四、通過(guò)Composer修改參數(shù)
五、修改請(qǐng)求參數(shù)之永久修改參數(shù),F(xiàn)iddlerScript修改參數(shù)
六、修改請(qǐng)求腳本代碼
if (oSession.HTTPMethodIs("POST") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 Body 數(shù)據(jù)
var requestBody=oSession.GetRequestBodyAsString();
// 解析 JSON
var json=Fiddler.WebFormats.JSON.JsonDecode(requestBody);
// 修改 JSON 參數(shù)
json.JSONObject["Body"]["kwy"]="value";
// 刪除 JSON 參數(shù)
json.JSONObject.Remove('key');
json.JSONObject["Body"].Remove("key");
// 將修改后的 JSON 轉(zhuǎn)換回字符串
var modifiedRequestBody=Fiddler.WebFormats.JSON.JsonEncode(json.JSONObject);
// 更新請(qǐng)求的 Body 數(shù)據(jù)
oSession.utilSetRequestBody(modifiedRequestBody);
}
if (oSession.HTTPMethodIs("POST") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 Body 數(shù)據(jù)
var requestBody=oSession.GetRequestBodyAsString();
// 修改參數(shù)
requestBody=requestBody.replace("param1=value1", "param1=newValue");
// 更新請(qǐng)求的 Body 數(shù)據(jù)
oSession.utilSetRequestBody(requestBody);
}
if (oSession.HTTPMethodIs("GET") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 URL
var url=oSession.fullUrl;
// 修改參數(shù)
url=url.replace("param1=value1", "param1=newvalue");
// 更新請(qǐng)求的 URL
oSession.fullUrl=url;
}
import System.Web;
if (oSession.HTTPMethodIs("GET") & & oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 URL
var url=oSession.fullUrl;
// 解析 URL 中的參數(shù)
var uri=new System.Uri(url);
var queryString=System.Web.HttpUtility.ParseQueryString(uri.Query);
// 刪除指定的參數(shù)
queryString.Remove("dt");
// 構(gòu)建新的 URL
var newUrl=uri.GetLeftPart(System.UriPartial.Path) + "?" + queryString.ToString();
// 更新請(qǐng)求的 URL
oSession.fullUrl=newUrl;
}
if (oSession.HTTPMethodIs("GET") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的頭部對(duì)象
var headers=oSession.oRequest.headers;
// 修改頭部的值
headers["key"]="value";
// 刪除指定的頭部
headers.Remove("key");
}
if (oSession.HTTPMethodIs("GET") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 Cookie 值
var cookieValue=oSession.oRequest["Cookie"];
// 添加cookie
cookieValue+=";key=value";
// 修改cookie
cookieValue=cookieValue.Replace("key=value", "key=newValue");
// 刪除cookie
cookieValue=cookieValue.Replace("key=value", "");
oSession.oRequest["Cookie"]=cookieValue
}
if (oSession.HTTPMethodIs("GET") && oSession.uriContains("example.com")) {
// 獲取請(qǐng)求的 Cookie 值
var cookieValue=oSession.oRequest["Cookie"];
var pattern="key=([^&]*)";
var regex=new System.Text.RegularExpressions.Regex(pattern);
var cookieValue=regex.Replace(cookieValue, "key=newValue");
oSession.oRequest["Cookie"]=cookieValue
}
FiddlerApplication.Log.LogString("cookie: " + cookieValue);
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。