1 引言
- 最近寫了一些簡單的爬蟲,感覺到爬蟲這個(gè)東西實(shí)踐大于理論,需要實(shí)際操作才能體會(huì)更深仲翎,寫下這篇短文壶辜,希望給有需要的同學(xué)在爬蟲入門的時(shí)候一點(diǎn)小小的幫助悯舟。
- 本文適合具備一定Python基礎(chǔ)的同學(xué),需要用到包括列表砸民,循環(huán)抵怎,函數(shù)奋救,文件讀寫等基礎(chǔ)知識,沒有接觸過Python的同學(xué)突擊了解一下即可反惕,動(dòng)手為先尝艘。
2 環(huán)境
- Python3.6
- IDE: Pycharm
- 操作系統(tǒng):Windows
3 基礎(chǔ)知識
本節(jié)介紹Requests庫和BeautifulSoup庫的基本用法,已經(jīng)有了解的同學(xué)可以直接跳過承璃。
我們的目標(biāo)網(wǎng)頁如下圖所示利耍,我們想要把紅色方框里的數(shù)據(jù)爬下來,單獨(dú)整理成一行盔粹,這樣就形成了每個(gè)樓盤一條記錄隘梨,就方便后續(xù)作分析了。
其實(shí)舷嗡,這些數(shù)據(jù)都在網(wǎng)頁源代碼里躺著轴猎,我們第一步需要做的得到源代碼,然后再去源代碼里找數(shù)據(jù)进萄,想要得到網(wǎng)頁源代碼捻脖,本文介紹使用python的requests庫:
-
Requests
在Chrome瀏覽器中,適用Ctrl+u快捷鍵可以看到網(wǎng)頁的源代碼中鼠,我們的目標(biāo)數(shù)據(jù)就在那一大串源代碼里可婶。日常瀏覽的時(shí)候,我們通過瀏覽器獲得網(wǎng)頁的源代碼援雇,經(jīng)瀏覽器解析和渲染后矛渴,就成了我們看到的模樣。
現(xiàn)在我們需要在Python里同樣獲得源代碼惫搏,本文使用第三方庫Requests具温,通過以下命令,就可以獲得我們需要的源代碼了筐赔。
# requests.get可以返回一個(gè)python response對象
response = requests.get("https://bj.lianjia.com/ershoufang/")
# response對象是二進(jìn)制的铣猩,我們需要通過.text方法將它轉(zhuǎn)化成文本,轉(zhuǎn)化之后就是Ctrl+u看到的樣子
response_text = response.text
獲得源代碼以后茴丰,我們要進(jìn)一步在源代碼里找到我們需要的數(shù)據(jù)达皿,網(wǎng)頁的源代碼是有一定的結(jié)構(gòu)的,類似
<li class="sellListContent"> 目標(biāo)數(shù)據(jù) </li>
這樣的結(jié)構(gòu)是一個(gè)個(gè)標(biāo)簽较沪,但是我們在上一步獲得的源代碼是一個(gè)超長的字符串鳞绕,我們需要將字符串重新轉(zhuǎn)化為有結(jié)構(gòu)的模式,這里使用第三方庫BeautifulSoup尸曼。
- BeautifulSoup
BeautifulSoup庫可以將源代碼轉(zhuǎn)化為BeautifulSoup對象们何,我們需要在BeautifulSoup對象中找到我們的目標(biāo)標(biāo)簽,然后提取目標(biāo)數(shù)據(jù)控轿,代碼如下
from bs4 import BeautifulSoup # python3已將BeautifulSoup庫集成到bs4中冤竹,需要先import
# 將上述文本轉(zhuǎn)化為BeautifulSoup對象拂封,"html.parser"是一種解剖器
bsobj = BeautifulSoup(response_text,"html.parser")
# 在BeautifulSoup對象里找到目標(biāo)內(nèi)容所在的標(biāo)簽
ul = bsobj.find("ul",{"class":"sellListContent"}) # 這里.find返回找到的第一個(gè)標(biāo)簽
# 由于標(biāo)簽是有層級結(jié)構(gòu)的,所以我們可以繼續(xù)在標(biāo)簽里找鹦蠕,這里.find_all則返回找到的所有符合要求的標(biāo)簽組成的列表
all_li = ul.find_all("li",{"class":"clear"})
基礎(chǔ)知識介紹到這里冒签,下面開始實(shí)戰(zhàn)。
4 開始爬蟲
本節(jié)定義了幾個(gè)函數(shù)钟病,實(shí)現(xiàn)了從標(biāo)簽里提取數(shù)據(jù)萧恕,并拼接成我們需要的格式,然后寫入文本文件肠阱。下面分別介紹:
- 函數(shù)getdata()票唆,從網(wǎng)頁爬取數(shù)據(jù)
我們期望實(shí)現(xiàn)以下效果:給函數(shù)一個(gè)網(wǎng)址,函數(shù)就返回我們需要的數(shù)據(jù)屹徘,代碼如下
import requests
from bs4 import BeautifulSoup
def getdata(url):
# 模擬一個(gè)請求頭走趋,目的是假裝我們是通過瀏覽器訪問的網(wǎng)頁
header = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"}
# 通過requests.get可以獲得網(wǎng)址為url的網(wǎng)頁的返回的一些數(shù)據(jù)
response = requests.get(url,headers=header)
# 由于返回的是二進(jìn)制,需要通過response.text轉(zhuǎn)化為文本
response_text = response.text
# 將上述文本轉(zhuǎn)化為BeautifulSoup對象噪伊,"html.parser"是一種解剖器
bsobj = BeautifulSoup(response_text,"html.parser")
# 在BeautifulSoup對象里找到目標(biāo)內(nèi)容所在的標(biāo)簽
ul = bsobj.find("ul",{"class":"sellListContent"})
# 再在標(biāo)簽里找到下級標(biāo)簽簿煌,返回的是所有標(biāo)簽組成的一個(gè)列表(也可以在上一步直接找,不過有可能找到一些包含我們不需要的數(shù)據(jù)的標(biāo)簽)
all_li = ul.find_all("li",{"class":"clear"})
housdata = []
# 由于每一個(gè)"li"都是一條記錄鉴吹,我們要循環(huán)將"li"里面的內(nèi)容取出來
for li in all_li:
record = ""
# 由于每一個(gè)"li"里面又有很多"div"姨伟,"div"里的內(nèi)容才是我們真正想要的,因此繼續(xù)找
all_div = li.find("div",{"class":"info clear"}).find_all("div")
# 將每個(gè)"div"里的內(nèi)容通過.get_text()方法取出來
for j in all_div:
j_text = j.get_text().strip().strip("\n") # 兩個(gè)strip先后去除取出來文本兩端的空格和換行符
# 然后將每個(gè)"div"里取出來的文本拼接起來
record = record + "@" + j_text
# 每個(gè)"li"都會(huì)返回一個(gè)record豆励,即一條記錄
# 將每個(gè)record都添加到housdata這個(gè)列表里
housdata.append(record)
# 最后返回整個(gè)housdata列表
return housdata
??定義好這個(gè)函數(shù)之后授滓,我們每輸入一個(gè)url,函數(shù)就可以返回包括該網(wǎng)頁中所有記錄的列表了。
??當(dāng)然,一個(gè)頁面并不能滿足要求耿芹,我們的目標(biāo)是所有網(wǎng)頁怠硼,因此只需要得到所有網(wǎng)頁,然后一個(gè)一個(gè)喂給getdata函數(shù)就可以了私沮,下面定義一個(gè)構(gòu)造網(wǎng)頁的函數(shù)始赎,我們給該函數(shù)一個(gè)數(shù)字(代表第幾頁),該函數(shù)就返回該頁的網(wǎng)址仔燕。
- 函數(shù)geturl()造垛,獲取頁面url
def geturl(num):
if num ==1 :
url = r"https://bj.lianjia.com/ershoufang/"
else:
url = "https://bj.lianjia.com/ershoufang/pg" + str(num) +"/"
return url
- 最后的工作
最后就是使用我們定義好的函數(shù),然后一頁一頁爬取晰搀,并寫入txt文本文件了五辽。
lianjia = open(r"C:\Users\lianjia.txt","a",encoding="utf-8")
for i in range(1, 940):
url = geturl(i)
housdata = getdata(url)
for line in housdata:
lianjia.write(line + "\n")
time.sleep(1)
print(i)
lianjia.close()
轉(zhuǎn)載請注明出處,有任何問題外恕,請聯(lián)系我的郵箱:oythonhill@163.com