1.1 輸入關鍵字,通過百度搜索來自指定網站的網頁,如鳳凰網。
1.2 下拉菜單和輸入框組合到一起,即網站地址既可以手動輸入,也可以通過下拉菜單選擇后自動輸入。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<script language="javascript" type="text/javascript">
function baiduSearch() {
window.open("http://www.baidu.com/baidu?word=" + formmain.kw.value + "&tn=bds&cl=3&ct=2097152&si=" + formmain.sitesearch.value + "&s=on");
//如果用漢語搜索,關鍵字最好是重新編碼:encodeToGb2312(formmain.kw.value)
}
</script>
<style>
.siteselect{
width:168px;
margin-left:-145px;
margin-left:-146px;
}
.iesitesearch{
font-size:14px;
height:16px;
width:145px;
margin-top:0px;
position:absolute;
left:5px;
}
</style>
<title>站內搜索</title>
</head>
<body>
<form id=formmain onsubmit="return checktype(this); search()" name="f" action=JavaScript:>
關鍵字:<input type="text" size=35 name="wd" id="kw" maxlength="100" title="輸入”搜索詞“,在下面區域單擊某一按鈕,即開始搜索!" /> 網站地址:
<span style="position:relative;">
<span style="margin-left:150px;overflow:hidden;">
<select class="siteselect" onchange="this.parentNode.nextSibling.value=this.value">
<option value="sohu.com">搜狐</option>
<option value="sina.com.cn">新浪</option>
<option value="163.com">網易</option>
<option value="qq.com">騰訊</option>
<option value="ifeng.com">鳳凰網</option>
</select>
</span><input id="sitesearch" name="sitesearch" class="iesitesearch" title="在前面輸入框中輸入“搜索詞“后,在此處可輸入網址(如sina.com.cn,前面不需要http://www.)或選擇某一特定網站,然后單擊“谷歌”或“百度”即可開始定向搜索!";>
<!--</span><input...的內容必須寫成一行,否則下拉菜單中選擇的內容無法顯示到輸入框-->
</span>
<input name="btnG3" type="button" value="百度" onclick="baiduSearch();" class="sitebai" />
</form>
</body>
</html>
搜索后的顯示頁面:
xml是基于 libxml2解析庫的Python封裝。libxml2是使用C語言編寫的,解析速度很好,不過安裝起來稍微有點復雜。安裝說明可以參考(http: //Lxml.de/installation.html),在CentOS7上中文安裝說明(http://www.cjavapy.com/article/64/),使用lxml庫來解析網絡爬蟲抓取到的HTML是一種非常高效的方式。lxml的html模塊特別適合處理HTML內容,它可以快速解析大型HTML文件,并提供XPath和CSS選擇器來查詢和提取數據。
參考文檔:https://www.cjavapy.com/article/65/
從網絡上抓取到的html的內容,有可能都是標準寫法,標簽什么的都閉合,屬性也是標準寫法,但是有可能有的網站的程序員不專業,這樣抓到的html解析就有可能有問題,因此,解析時先將有可能不合法的html解析為統一的格式。避免為后續的解析造成困擾。
1、lxml.html
lxml.html是專門用于解析和處理HTML文檔的模塊。它基于lxml.etree,但是為HTML文檔的特點做了優化。lxml.html能夠處理不良形式的HTML代碼,這對于解析和爬取網頁尤其有用。
>>> import lxml.html
>>> broken_html = '<ul class="body"><li>header<li>item</ul>'
>>> tree = lxml.html.fromstring(broken_html) #解析html
>>> fixed_html = lxml.html.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>
2、lxml.etree
lxml.etree是lxml庫中用于處理XML文檔的模塊。它基于非常快的XML解析庫libxml2,提供了一個類似于標準庫xml.etree.ElementTreeAPI的接口,但是在性能和功能性方面要更加強大。lxml.etree支持XPath、XSLT、和Schema驗證等高級XML特性。
>>> import lxml.etree
>>> broken_html = '<ul class="body"><li>header<li>item</ul>'
>>> tree = lxml.etree.fromstring(broken_html) #解析html
>>> fixed_html = lxml.etree.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>
通過以上可以看出,lxml可以正確解析兩側缺失的括號,并閉合標簽,但不會額外增加<html>和<body>標簽。
若在html中找到我們想要的內容,用lxml有幾種不同的方法,XPath選擇器類似Beautiful Soup的find()方法。CSS選擇器用法和jQuery中的選擇器類似。兩種選擇器都可以用來查找文檔中的元素,但它們各有特點和適用場景。XPath是一種在XML文檔中查找信息的語言。它可以用來遍歷XML文檔的元素和屬性。CSS選擇器通常用于選擇和操作HTML文檔中的元素。
1、XPath選擇器(/單斜杠表示絕對查找,//雙斜杠表示相對查找)
from lxml import etree
source_html = """
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
"""
html = etree.HTML(source_html)
print(html)
result = etree.tostring(html)#會對的html標簽進行補全
print(result.decode("utf-8"))
輸出結果:
<Element html at 0x39e58f0>
<html><body><div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li></ul>
</div>
</body></html>
1)獲取某個標簽的內容(a標簽后不需要加斜杠,否則會報錯)
#第一種寫法
html = etree.HTML(source_html)
html_data = html.xpath('/html/body/div/ul/li/a')#絕對查找
#html_data = html.xpath('//li/a')#相對查找
print(html)
for i in html_data:
print(i.text)
輸出結果:
<Element html at 0x14fe6b8>
first item
second item
third item
fourth item
fifth item
#第二種寫法
#在要找的標簽后面加/text(),就是獲取標簽中的文本內容,結果中直接就是文本內容了,不用在通過text屬性獲取了。
html = etree.HTML(source_html)
html_data = html.xpath('/html/body/div/ul/li/a/text()')#絕對查找
#html_data = html.xpath('//li/a/text()')#相對查找
print(html)
for i in html_data:
print(i)
輸出結果:
<Element html at 0x128e3b7>
first item
second item
third item
fourth item
fifth item
2)獲取a標簽下的屬性
html = etree.HTML(source_html)
html_data = html.xpath('//li/a/@href') #相對查找
#html_data = html.xpath('/html/body/div/ul/li/a/@href') #絕對查找
for i in html_data:
print(i)
輸出結果:
link1.html
link2.html
link3.html
link4.html
link5.html
3)查找a標簽屬性等于link2.html的內容
html = etree.HTML(source_html)
html_data = html.xpath('/html/body/div/ul/li/a[@href="link2.html"]/text()')絕對查找
#html_data = html.xpath('//li/a[@href="link2.html"]/text()')#相對查找
print(html_data)
for i in html_data:
print(i)
輸出結果:
['second item']
second item
4)查找最后一個li標簽里的a標簽的href屬性
html = etree.HTML(source_html)
html_data = html.xpath('//li[last()]/a/text()')
print(html_data)
for i in html_data:
print(i)
輸出結果:
['fifth item']
fifth item
5)查找倒數第二個li標簽里a標簽的href屬性
html = etree.HTML(source_html)
html_data = html.xpath('//li[last()-1]/a/text()')
print(html_data)
for i in html_data:
print(i)
輸出結果:
['fourth item']
fourth item
6)查找某個標簽id屬性值等于value的標簽
//*[@id="value"]
7)使用chrome瀏覽器提取某個標簽的XPath
2、CSS選擇器(基本上和jQuery選擇器用法一樣)
選擇器 | 描述 |
* | 選擇所有標簽 |
a | 選擇<a>標簽 |
.link | 選擇所有class = 'link'的元素 |
a.link | 選擇class = 'link'的<a>標簽 |
a#home | 選擇id = 'home'的<a>標簽 |
a > span | 選擇父元素為<a>標簽的所有<span>子標簽 |
a span | 選擇<a>標簽內部的所有<span>標簽 |
使用示例:
>>> html = """<div>
<tr id="places_area_row" class="body">
<td>header</td>
<td class="w2p_fw">item1</td>
<td class="w2p_fw">item2</td>
<td class="w2p_fw">item3</td>
<td><tr><td class="w2p_fw">header</td>
<td class="w2p_fw">item4</td>
<td class="w2p_fw">item5</td>
<td class="w2p_fw">item6</td></tr></td>
</tr>
</div>"""
>>> tree = lxml.html.fromstring(html)
>>> td = tree.cssselect('tr#places_area_row > td.w2p_fw')[0]
>>> htmlText = td.text_content()
>>> print htmlText
item1
參考文檔:https://www.cjavapy.com/article/65/
?
2年前做了一個基于element-ui的layout組件發布到npm package上去,廣受大家的歡迎,下載量每周頗升。這個組件的好處在于開發者不用寫太多html代碼和邏輯,只要通過配置json的方式就能馬上生成后臺,包括菜單欄和導航面包屑等一鍵生成,還能根據不同的需求做定制化后臺界面,就像拼積木一樣,讓用戶只專注于內容核心代碼的開發。現在還沒做大范圍的推廣,如果我覺得它做得足夠好,我一定會放到npm上推薦給各位讀者使用哈。當初為了解答網友的疑問,我還專門建立了該組件的官網。logo看起來有沒有很熟悉?哈哈哈,它其實就是element-ui的logo進行改造的,意義就是告訴使用者,這是element-ui功能的組合加強版。
為了迎合公司的OKR,我提出了對表單表格組件的封裝。為什么我會有這個想法?其實這個組件我很早就想做了,只是以前做的是基于UI層面的,近期我接手了公司的一個項目叫童畫,每天做的事情感覺就是復制粘貼,修改部分不同的功能和字段名稱。組件的意義在于可以在遇到同一類設計場景時,可以復用,從而減少設計的時間和形成產品的統一性。傳統的搜索表單不就是這樣嗎?上面是表單搜索字段,中間是搜索結果的表格,下面是搜索結果的分頁。把表單和表格組合起來的好處在于很多搜索字段都是基于表格組件的某些字段,那我根據search字段進行篩選不就可以了么,很久之前,我們總是在吐槽產品經理總是喜歡截圖現有功能,然后做字段修改,搞成原型扔給前端。如果前端也能像他這樣簡單,那該多好呀,類似這樣的想法油然而生。剛開始我只是為了方便我的工作,沒想到領導卻重視了起來,想把這個組件推廣給公司其他十幾個前端同事使用,于是乎,我便認真開搞了起來。有理論還不行,得有場景實踐,剛好公司的項目童畫有很多場景,我根據它里面的場景,做了很多功能的封裝和兼容。
寫到這里,有人會說了,這不就是CRUD組件嗎?有這想法的話,說明你還太年輕和小看這個組件的功能了。傳統的CRUD組件靈活性不是很高,這個組件的好處是配置即可用,不用考慮其他搜索,翻頁,清空等各種邏輯,讓組件達到高度復用,封裝了場景的插槽類型,但為了防止翻車,我還是預留了變態需求的插槽。字段的使用更多采用elementUI的命名方式,讓使用者減少學習成本。這樣做的好處是什么呢?首先,前端再也不用寫頁面了,其次,對于比較規矩的搜索表單頁面,完全可以通過請求接口的形式交給后端來配置呈現頁面即可,根本沒有前端什么事了,前端的工作可以解放出來做更復雜的功能開發。
為了使用方便,我把它做成了組件并放到了公司的私服上,接下來的工作就是寫文檔啦,以下是部分文檔的編寫,因為時間問題,沒來得及好好檢查,各位看官將就看一下就行啦。
export default {
options: {
request: {
api: '/student/web/student/enroll/list',
method: 'GET',
paramMap: {
index: 'pageIndex',
limit: 'pageSize'
},
resultMapping: {
total: 'total',
data: 'pageData'
}
},
size: '', // medium/mini/small, 默認medium
labelWidth: 90,
submitBtn: true, // 搜索按鈕,默認true,非必填
submitText: '查詢', // 搜索按鈕的文字,默認查詢,非必填
clearBtn: true, // 清除按鈕,默認true
clearSize: 'mini', // medium/mini/small, 默認medium
clearText: '清除', // 清除按鈕的文字,默認清除,非必填
column: [
{
slotType: 'selection'
},
{
prop: 'keyword',
label: '學員/家長',
search: true,
hide: true
},
{
prop: 'studentName',
label: '學員'
},
{
prop: 'telephone',
label: '家長手機號',
width: 130
},
{
prop: 'type',
label: '報名類型',
width: 90,
search: true,
type: 'select',
slot: true,
slotType: 'text',
slotArray: [{
label: '新報',
value: 1
},
{
label: '續報',
value: 2
}],
dicData: [{
label: '新報',
value: 1
},
{
label: '續報',
value: 2
}]
},
{
prop: 'courseFee',
label: '繳費金額',
slot: true,
slotType: 'regEx',
regEx: '¥{{courseFee/100}}'
},
{
prop: 'payType',
label: '支付方式',
search: true,
type: 'select',
width: 100,
dicData: [
{
label: '微信',
value: '微信'
},
{
label: '支付寶',
value: '支付寶'
},
{
label: '銀行卡轉賬',
value: '銀行卡轉賬'
},
{
label: '其它',
value: '其它'
}
]
},
{
prop: 'courseCount',
label: '報名課時'
},
{
prop: 'followTeacher',
label: '跟進人'
},
{
prop: 'createTime',
label: '報名時間',
param: 'beginTime,endTime',
format: 'yyyy 年 MM 月 dd 日',
valueFormat: 'timestamp',
search: true,
width: 160,
type: 'daterange'
},
{
prop: 'auditor',
label: '報名老師',
search: true,
param: 'teacherId', // 修正請求參數名
type: 'select',
dicData: [],
dicUrl: '/org/web/org/user/list/teacher',
dicMap: {
label: 'userName',
value: 'id'
}
},
{
prop: 'status',
label: '報名狀態',
slot: true,
slotType: 'tag',
width: 110,
slotArray: [{
type: 'warning',
label: '待審核',
value: 1
},
{
type: 'danger',
label: '審核不通過',
value: 3
},
{
type: 'success',
label: '審核通過',
value: 2
}],
dicUrl: ''
},
{
prop: 'operation',
label: '操作',
width: 80,
slot: true,
slotType: 'operation',
slotArray: [
{
label: '去審核',
value: 'handle',
filter: ({status}) => {
return status === 1
}
}
]
}
]
}
}
生成的頁面
最后,感謝同事世丞在字段命名上給了很多建議,同時也感謝領導給了很多刁難的意見,讓這個組件的功能越發強大,也讓開發者使用更方便,達到配置即可使用的地步。當然了,組件還需要更多場景的訓練才能真正實現各種功能的兼容。后期我希望可以盡快放到layout官網上,供大家使用。
一個會美工與后端PHP/nodejs的全棧工程師
更多學習內容歡迎關注
微信公眾號 :程序員周先生
*請認真填寫需求信息,我們會在24小時內與您取得聯系。