時間:2023-10-12 10:48:01 | 來源:網(wǎng)站運營
時間:2023-10-12 10:48:01 來源:網(wǎng)站運營
網(wǎng)絡(luò)爬蟲系列 靜態(tài)網(wǎng)頁與動態(tài)網(wǎng)頁的簡單實戰(zhàn):conda install requests
安裝BeautifulSoupconda install bs4
安裝Seleniumconda install selenium
import requestsfrom bs4 import BeautifulSoupimport numpy as npimport pandas as pd
使用.get()函數(shù)獲得網(wǎng)站資源,顯然這里使用了http訪問方法中的get方法。服務(wù)器返回代碼200,表示http請求-響應(yīng)成功,我們已經(jīng)獲得網(wǎng)頁數(shù)據(jù)。url = 'http://detail.zol.com.cn/cell_phone_index/subcate57_0_list_1_0_1_2_0_1.html'data = requests.get(url, timeout=1) # timeout設(shè)置等待時間,超時未收到響應(yīng)的話則返回連接失敗data
<Response [200]>
requests會根據(jù)獲得的數(shù)據(jù)來推測網(wǎng)頁的字符編碼,但這未必準(zhǔn)確。data.encoding # 查看網(wǎng)頁編碼
'GBK'
#data.encoding = 'UTF-8' #如果通過.text得到的字符串出現(xiàn)亂碼,則需要用此行代碼重新編碼。正確的網(wǎng)頁字符編碼可以在HTML的head里查看。d_text = data.textd_text[:2000]
'<!DOCTYPE html>/r/n<html>/r/n<head>/r/n<meta charset="GBK" />/n/t<title>【最熱門手機大全】最熱門手機報價及圖片大全-ZOL中關(guān)村在線</title>/n/t<meta name="keywords" content="最熱門手機,最熱門手機報價,最熱門手機價格,手機大全,手機最新報價" />/n/t<meta name="description" content="ZOL中關(guān)村在線提供最熱門手機最新價格及經(jīng)銷商報價,包括最熱門手機大全,最熱門手機參數(shù),最熱門手機評測,最熱門手機圖片,最熱門手機論壇等詳細(xì)內(nèi)容,為您購買最熱門手機提供全面參考" />/n<meta http-equiv="Cache-Control" content="no-siteapp"/>/n/t<meta http-equiv="Cache-Control" content="no-transform"/>/n/t<meta name="applicable-device" content="pc">/n/t<meta name="referrer" content="unsafe-url">/n/t<meta http-equiv="mobile-agent" content="format=xhtml; url=https://wap.zol.com.cn/list/57.html?j=simple"/>/n<meta http-equiv="mobile-agent" content="format=html5; url=https://wap.zol.com.cn/list/57.html"/>/n<meta name="mobile-agent" content="format=wml;url=https://wap.zol.com.cn/list/57.html"/>/n<meta name="mobile-agent" content="format=xhtml;url=https://wap.zol.com.cn/list/57.html"/>/n<link rel="alternate" media="only screen and(max-width:640px)" href="https://wap.zol.com.cn/list/57.html"/>/n<script>(function(){var fromVal=document.location.href.indexOf("from=jinritoutiao") > -1 ? "?from=jinritoutiao" : "";var a=1,d="https://wap.zol.com.cn/list/57.html"+fromVal,b=document.cookie,c=document.referrer;b&&b.match(/mobile_agent_global_dapter=([^;$]+)/)&&(a=b.match(/mobile_agent_global_dapter=([^;$]+)/)[1]);if(1===a&&""!==d&&(/AppleWebKit.*Mobile/i.test(navigator.userAgent)||/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE|TAH-AN00m/.test(navigator.userAgent))&&0>window.location.href.indexOf("?via=")){a=new Date;c=""===c?"none":-1<c.indexOf("?")?c+"&pcjump=1":c+"?pcjump=1";b&&(a.setDate(a.getDate()+1),document.cookie="PC2MRealRef="+escape(c)+";expires="+a.toGMTString()+/r/n"; domain=.zol.com.cn; path=/");try{/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)&&(window.location.href=d)}catch(e){}}})();</script>/n<script type="text/javascript" src="//icon.zol-img.com.cn/swfobject.'
d_text里的數(shù)據(jù)只是字符串格式,BeautifulSoup不能直接解析。首先轉(zhuǎn)換成BeautifulSoup對象,它是一個復(fù)雜的樹形結(jié)構(gòu),就像開發(fā)者工具里看到的層次分明的HTML。soup = BeautifulSoup(d_text)type(soup)
bs4.BeautifulSoup
下面開始提取我們需要的數(shù)據(jù)。可用.find(), .find_all(), .select()。以.select()為例,它是一個CSS選擇器,根據(jù)HTML的標(biāo)簽、屬性、層級關(guān)系來定位我們需要的數(shù)據(jù)。phone_name = soup.select('div.content > div.pic-mode-box > ul.clearfix > li > h3 > a') # 根據(jù)HTML的層次結(jié)構(gòu)定位所需要的數(shù)據(jù)phone_name[:5]
[<a href="/cell_phone/index1345834.shtml" target="_blank" title="vivo X60 Pro+(8GB/128GB/全網(wǎng)通/5G版)微云臺雙主攝,驍龍888,蔡司聯(lián)合影像系統(tǒng)">vivo X60 Pro+(8GB/128GB/全網(wǎng)通/5G版) <span>微云臺雙主攝,驍龍888,蔡司聯(lián)合影像系統(tǒng)</span></a>, <a href="/cell_phone/index1337045.shtml" target="_blank" title="OPPO Reno5 Pro(8GB/128GB/全網(wǎng)通/5G版)閃電啟動,星鉆光芒設(shè)計,6400萬水光人像四攝">OPPO Reno5 Pro(8GB/128GB/全網(wǎng)通/5G版) <span>閃電啟動,星鉆光芒設(shè)計,6400萬水光人像四攝</span></a>, <a href="/cell_phone/index1337287.shtml" target="_blank" title="華為Mate40 Pro(8GB/256GB/全網(wǎng)通/5G版/玻璃版)麒麟9000,88°超曲環(huán)幕屏,66W快充,50W無線快充,IP68級防水防塵,3D人臉識別">華為Mate40 Pro(8GB/256GB/全網(wǎng)通/5G版/玻璃版) <span>麒麟9000,88°超曲環(huán)幕屏,66W快充,50W無線快充,IP68級防水防塵,3D人臉識別</span></a>, <a href="/cell_phone/index1345628.shtml" target="_blank" title="三星Galaxy S21 Ultra(12GB/256GB/全網(wǎng)通/5G版)驍龍888,1.08億像素,120Hz護目屏,支持Spen">三星Galaxy S21 Ultra(12GB/256GB/全網(wǎng)通/5G版) <span>驍龍888,1.08億像素,120Hz護目屏,支持Spen</span></a>, <a href="/cell_phone/index1330551.shtml" target="_blank" title="三星Galaxy Note 20 Ultra(12GB/256GB/全網(wǎng)通/5G版)S Pen,三星筆記,120Hz自適應(yīng)屏幕,專業(yè)視頻拍攝">三星Galaxy Note 20 Ultra(12GB/256GB/全網(wǎng)通/5G版) <span>S Pen,三星筆記,120Hz自適應(yīng)屏幕,專業(yè)視頻拍攝</span></a>]
代碼至此,我們已經(jīng)很接近得到最終的數(shù)據(jù)了。從上述的結(jié)果來看,手機信息就藏在a標(biāo)簽里面,下面使用.get_text()函數(shù)提取出來。for i in phone_name[:5]: name = i.get_text() # .get.text()函數(shù)可以獲取標(biāo)簽里的文本 print(name)
vivo X60 Pro+(8GB/128GB/全網(wǎng)通/5G版) 微云臺雙主攝,驍龍888,蔡司聯(lián)合影像系統(tǒng)OPPO Reno5 Pro(8GB/128GB/全網(wǎng)通/5G版) 閃電啟動,星鉆光芒設(shè)計,6400萬水光人像四攝華為Mate40 Pro(8GB/256GB/全網(wǎng)通/5G版/玻璃版) 麒麟9000,88°超曲環(huán)幕屏,66W快充,50W無線快充,IP68級防水防塵,3D人臉識別三星Galaxy S21 Ultra(12GB/256GB/全網(wǎng)通/5G版) 驍龍888,1.08億像素,120Hz護目屏,支持Spen三星Galaxy Note 20 Ultra(12GB/256GB/全網(wǎng)通/5G版) S Pen,三星筆記,120Hz自適應(yīng)屏幕,專業(yè)視頻拍攝
我們已經(jīng)知道如何利用.get_text()函數(shù)可以獲得數(shù)據(jù),所以到了爬蟲的最后一步:存儲數(shù)據(jù)。這一步我們使用pandas第三方庫。phone_info = pd.DataFrame(columns=['name'])phone_info['name'] = [i.get_text() for i in phone_name]phone_info.head()
name0 vivo X60 Pro+(8GB/128GB/全網(wǎng)通/5G版) 微云臺雙主攝,驍龍888,...1 OPPO Reno5 Pro(8GB/128GB/全網(wǎng)通/5G版) 閃電啟動,星鉆光芒設(shè)計,...2 華為Mate40 Pro(8GB/256GB/全網(wǎng)通/5G版/玻璃版) 麒麟9000,88°...3 三星Galaxy S21 Ultra(12GB/256GB/全網(wǎng)通/5G版) 驍龍888,1...4 三星Galaxy Note 20 Ultra(12GB/256GB/全網(wǎng)通/5G版) S P...
以csv格式保存數(shù)據(jù)至當(dāng)前目錄。此處注意編碼問題。phone_info.to_csv('phone_info.csv', encoding='utf_8_sig')
以上是一個簡單又完整的爬蟲例子,后面的代碼都是基于這個思路編寫,大家讀懂了上述內(nèi)容的話,相信接下來的內(nèi)容也能很快看懂。def multi_url(): phone_dataset = [] # 存儲數(shù)據(jù) for num in range(1, 3): # 改變地址的特定部分 u = f'http://detail.zol.com.cn/cell_phone_index/subcate57_0_list_1_0_1_2_0_{num}.html' # 檢查地址是否正確 try: data = requests.get(u, timeout=1) data.encoding # 理論上,若URL錯誤,則無法獲得網(wǎng)頁資源,從而無法進(jìn)行encoding,程序會報錯 except: print('已到達(dá)最后一頁!') return phone_dataset d_text = data.text # 采集當(dāng)前頁面的數(shù)據(jù) soup = BeautifulSoup(d_text) phone_name = soup.select('div.content > div.pic-mode-box > ul.clearfix > li > h3 > a') # 儲存 for j in phone_name: phone_dataset.append(j.get_text()) return phone_datasetphone2 = multi_url()print(phone2[-3:])
['華為nova 7 SE(8GB/128GB/5G版/全網(wǎng)通) 麒麟820,6400萬高清AI四攝,40W超級快充', '華為nova 5 Pro(8GB/128GB/全網(wǎng)通) 3200萬超高清自拍,人像超級夜景', '榮耀30S(8GB/128GB/全網(wǎng)通/5G版) 5G雙模,麒麟820,40W快充']
def multi_next_page(): phone_dataset = [] # 存儲數(shù)據(jù) # 采集第一頁數(shù)據(jù) data = requests.get('http://detail.zol.com.cn/cell_phone_index/subcate57_0_list_1_0_1_2_0_1.html').text soup = BeautifulSoup(data) phone_name = soup.select('div.content > div.pic-mode-box > ul.clearfix > li > h3 > a') for i in phone_name: phone_dataset.append(i.get_text()) # 開始多頁循環(huán) base_url = 'http://detail.zol.com.cn/' num = 1 while num < 2: try: p = soup.select('a.next') # 定位到“下一頁”按鈕 page = p[0].get('href') # 通過.get('herf')來獲得下一頁的部分地址 num += 1 print(f'第{num}頁采集ing...') except: print('采集完成!') return phone_dataset url = base_url + str(page) # 合并成完整的地址 # 采集數(shù)據(jù) data = requests.get(url).text soup = BeautifulSoup(data) phone_name = soup.select('div.content > div.pic-mode-box > ul.clearfix > li > h3 > a') for i in phone_name: phone_dataset.append(i.get_text()) return phone_datasetphone3 = multi_next_page()print(phone3[-3:])
['華為nova 7 SE(8GB/128GB/5G版/全網(wǎng)通) 麒麟820,6400萬高清AI四攝,40W超級快充', '華為nova 5 Pro(8GB/128GB/全網(wǎng)通) 3200萬超高清自拍,人像超級夜景', '榮耀30S(8GB/128GB/全網(wǎng)通/5G版) 5G雙模,麒麟820,40W快充']
注意到,我們找到的Request URL,與茅臺的原始地址是完全不一樣的。
url = r'http://you.163.com/xhr/comment/listByItemByTag.json?__timestamp=1612421786209&itemId=3995885&tag=%E5%85%A8%E9%83%A8&size=20&page=1&orderBy=0&oldItemTag=%E5%85%A8%E9%83%A8&oldItemOrderBy=0&tagChanged=0'data = requests.get(url)d_text = data.textd_text[:2000]
'{"code":"200","data":{"pagination":{"page":1,"size":20,"totalPage":1288,"total":25748,"lastPage":false},"commentList":[{"skuInfo":["規(guī)格:1瓶"],"frontUserName":"小****","frontUserAvatar":"https://yanxuan.nosdn.127.net/4719d50913c28fac5aa575ba6f21fe20","content":"物流非???,質(zhì)量非常好,客服態(tài)度非常好,相信我自己還能再中一次!","createTime":1603867171787,"picList":["https://yanxuan.nosdn.127.net/05b30e92fd11ddef6decdded5c674253.jpg","https://yanxuan.nosdn.127.net/110e362866760ce9b0d7ccdee76f4bfe.jpg"],"commentReplyVO":null,"memberLevel":5,"appendCommentVO":{"id":143233162,"createTime":1603867470466,"content":"很有品質(zhì)保證,買買買?。?!","picList":["https://yanxuan.nosdn.127.net/8e63dc16f7be996cafbb8094fd039f1a.jpg","https://yanxuan.nosdn.127.net/66825d8d503f08074fa1ef7fd88a14f3.jpg"],"commentReplyVO":null},"star":5,"itemId":3995885},{"skuInfo":["規(guī)格:1瓶"],"frontUserName":"用****8","frontUserAvatar":"https://yanxuan.nosdn.127.net/9e6dadfc9eb0954061797dfd88f13980.jpg","content":"終于搶到一瓶,感謝網(wǎng)易嚴(yán)選!希望能再給我中一瓶!","createTime":1605188815733,"picList":["https://yanxuan.nosdn.127.net/8bfe48109701139745ac8c6018bf38f5.jpg"],"commentReplyVO":null,"memberLevel":4,"appendCommentVO":null,"star":5,"itemId":3995885},{"skuInfo":["規(guī)格:1瓶"],"frontUserName":"r****0","frontUserAvatar":null,"content":"終于讓我搶到一瓶,太好了,搶不到只能從黃牛手里拿了","createTime":1606895108114,"picList":["https://yanxuan.nosdn.127.net/f94f2a8d0689622d5391aa7b29371522.jpg"],"commentReplyVO":null,"memberLevel":5,"appendCommentVO":null,"star":5,"itemId":3995885},{"skuInfo":["規(guī)格:1瓶"],"frontUserName":"1****3","frontUserAvatar":"http://yanxuan.nosdn.127.net/bb31a487ad26923bcf115f896e789ebf","content":"速度很快,酒不錯,包裝很到位,很好,網(wǎng)易嚴(yán)選,很好,產(chǎn)地直接發(fā)貨,厲害了,支持","createTime":1603806876726,"picList":["https://yanxuan.nosdn.127.net/0dfc65a5b6b475175600f9f7908483ef.jpg","https://yanxuan.nosdn.127.net/d8d638707f3541da4205b9a4af4ea072.jpg","https://yanxuan.nosdn.127.net/f71bbb359b0f59bd28c96792836e5869.jpg","https://yanxuan.nosdn.127.net/e73fb3856d31edcd2f8c25ffe9465427.jpg","https://yanxuan.nosdn.127.net/97266996534f'
import jsonjson_data = json.loads(d_text)type(json_data)
dict
這里的json數(shù)據(jù)存在復(fù)雜的字典與列表嵌套(大家可以自行print出來觀察),肉眼不容易看清楚嵌套關(guān)系,但開發(fā)者工具提供了良好的可視化(Network——Preview),正如上一幅圖片所示。根據(jù)其中的嵌套邏輯,我們先找到了第一條評論。comment_list = json_data['data']['commentList'][0]['content']comment_list
從上一幅圖片看到,data隔離有一個大括號 { ,因此這一層是字典;而 0 隔壁有一個中括號 [ ,所以這層是列表。以此類推。
'物流非???,質(zhì)量非常好,客服態(tài)度非常好,相信我自己還能再中一次!'
在開發(fā)者工具里對比觀察第一、第二條評論的索引,我們發(fā)現(xiàn)'data''commentList''content'這三個索引值是固定不變的,只有0需要遞增到1,因此我們只需要運用循環(huán)語句,改變第三個索引值,就能獲得其余的評價內(nèi)容。同時注意單頁的評價數(shù),下面提供兩種方法,推薦使用第二條語句。len(json_data['data']['commentList']) # 使用函數(shù)計算本頁評價的數(shù)量json_data['data']['pagination']['size'] # json數(shù)據(jù)也交代了該頁的評價數(shù),可以直接索引獲取
comment_list = [json_data['data']['commentList'][i]['content'] for i in range(20)]comment_list
['物流非??欤|(zhì)量非常好,客服態(tài)度非常好,相信我自己還能再中一次!', '終于搶到一瓶,感謝網(wǎng)易嚴(yán)選!希望能再給我中一瓶!', '終于讓我搶到一瓶,太好了,搶不到只能從黃牛手里拿了', '速度很快,酒不錯,包裝很到位,很好,網(wǎng)易嚴(yán)選,很好,產(chǎn)地直接發(fā)貨,厲害了,支持', '好不容易搶到一瓶,真心不容易。但是也非常幸運吧。網(wǎng)易幾年的老用戶了,東西都不錯,價格也便宜。沒啥理由不選網(wǎng)易嚴(yán)選的東西。以后還會一如既往地選擇嚴(yán)選。', '幾個平臺只有網(wǎng)易搶到了,包裝完美,有嚴(yán)選的溯源碼是正品,感謝三石??!再接再厲再來一瓶!!', '嚴(yán)選還有專門的溯源標(biāo)簽,點贊,飛天真香呀,順豐超快,開森^_^', '貼嚴(yán)選標(biāo)簽了,看著很好,舍不得拆開看里面的酒,應(yīng)該沒問題。希望還能再買到', '物流很快,隔天就到了,酒完美無瑕疵,還會回購的', '酒收到了、包裝完美、貨真價實。感謝網(wǎng)易這么好的購物平臺,晚上就和朋友們喝了去', '第1次喝到平價的茅臺,平常喝的都是3000多一瓶。迫不及待與好友共飲,大家合作都比較愉快。好酒!', '努力了幾天搶到了,這么多年老用戶了不讓我買到,我會心寒的,不錯,速度很快,包裝很妥帖,有海綿墊瓶蓋也有海綿墊,防護工作做的很好,家里有幾樣?xùn)|西常年用嚴(yán)選的,加把勁再讓我搶一瓶,這才對得起我的支持 ', '包裝太好了,太精美了,網(wǎng)易云縣良心良心。以后購物就在網(wǎng)易嚴(yán)選吶。', '完美,很開心能搶到,感謝平臺,平臺的服務(wù)也很好', '不錯不錯!幾天努力終于搶到了了,快遞速度很快,產(chǎn)品保護周全,安全收到了,各方面都很好,好評!', '網(wǎng)易嚴(yán)選非常靠譜,值得信賴!多年的客戶了,醬香經(jīng)典、茅臺最醇!非常不錯,留著過年和家人一起喝,感謝網(wǎng)易嚴(yán)選!', '發(fā)貨速度非常快,第二天就到了,驗看了一下,包裝很好,是正品,值得購買。', '非常漂亮的茅臺酒,網(wǎng)易嚴(yán)選必出精品,超級喜歡,物流也非常不錯,還要繼續(xù)購買', '包裝很好,酒品很好。非常完美', '未填寫評價內(nèi)容']
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsimport time
selenium依賴瀏覽器程序而運行,因此第一步就需要給它定義一個瀏覽器。運行本行代碼會彈出瀏覽器窗口。文件夾里提供一個微型的88.0版本谷歌瀏覽器,當(dāng)然大家也可以用自己喜歡的瀏覽器。driver = webdriver.Chrome(executable_path='./chromedriver.exe')driver.get(r'http://you.163.com/item/detail?id=3995885&_stat_area=mod_16_item_16&_stat_id=1005002&_stat_referer=itemList')time.sleep(2) # 相當(dāng)于給代碼運行添加一個空白過程,便于等待頁面加載
商品的首頁不會出現(xiàn)評論,需要點擊“評論”按鈕,等待評論內(nèi)容加載后才能爬取。這就需要讓selenium模擬真人進(jìn)行鼠標(biāo)操作。button = driver.find_element_by_css_selector('li.item-1') # 通過CSS選擇器定位“評論”按鈕action = ActionChains(driver).move_to_element(button) # 模擬將鼠標(biāo)懸停到按鈕上action.click(button).perform() # .click()即點擊,perform()表示執(zhí)行上述所有動作鏈time.sleep(1)
將頁面拉到最底部,從而加載本頁所有評論。driver.execute_script("var q=document.documentElement.scrollTop=10000")
下面解析HTML的操作與BeautifulSoup類似,selenium也可以用CSS選擇器定位特定數(shù)據(jù),然后用.text獲得文本。comment_list = driver.find_elements_by_css_selector('div.content.f-breakall')comment_list[:5]
[<selenium.webdriver.remote.webelement.WebElement (session="33efbd2ce88b7c5d03394f6eaa65503c", element="6d89b995-76ef-4ffd-9b74-80a5a8e68873")>, <selenium.webdriver.remote.webelement.WebElement (session="33efbd2ce88b7c5d03394f6eaa65503c", element="44819238-ae3d-4212-b452-10eae73a6c27")>, <selenium.webdriver.remote.webelement.WebElement (session="33efbd2ce88b7c5d03394f6eaa65503c", element="df90dd8f-41a6-471f-9cde-ccf7d48cafc5")>, <selenium.webdriver.remote.webelement.WebElement (session="33efbd2ce88b7c5d03394f6eaa65503c", element="f3469893-c40e-4cfd-822f-749b86054382")>, <selenium.webdriver.remote.webelement.WebElement (session="33efbd2ce88b7c5d03394f6eaa65503c", element="58b21810-515a-4cde-8786-408d8ce73b49")>]
comment_text = [i.text for i in comment_list]comment_text[:5]
['物流非??欤|(zhì)量非常好,客服態(tài)度非常好,相信我自己還能再中一次!', '[追評] 很有品質(zhì)保證,買買買?。。?#39;, '終于搶到一瓶,感謝網(wǎng)易嚴(yán)選!希望能再給我中一瓶!', '終于讓我搶到一瓶,太好了,搶不到只能從黃牛手里拿了', '速度很快,酒不錯,包裝很到位,很好,網(wǎng)易嚴(yán)選,很好,產(chǎn)地直接發(fā)貨,厲害了,支持']
關(guān)鍵詞:簡單,實戰(zhàn),動態(tài),靜態(tài),爬蟲,網(wǎng)絡(luò),系列
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。