一、環境搭建
1、安裝python-3.5.2-amd64和pycharm-community-2016.3.2
參考http://jingyan.baidu.com/article/a17d5285ed78e88098c8f222.html?st=2&net_type=&bd_page_type=1&os=0&rst=&word=www.10010
2、配置網頁解析相關庫
以管理員身份運行命令提示符
1)pip3 install beautifulsoup4
2)pip3 install requests
3)pip3 install lxml
二、源代碼
1、導入beautifulsoup和requests庫
# -*- coding: utf-8 -*-from bs4 import BeautifulSoupimport requests
2、寫爬蟲主函數
def spider_1(url): response = requests.get(url) soup = BeautifulSoup(response.text,'lxml') titles = soup.select('dd > p.title > a') # 標題 hrefs = soup.select('dd > p.title > a') # 鏈接 details = soup.select('dd > p.mt12') # 建築信息 courts = soup.select('dd > p:nth-of-type(3) > a') # 小區 adds = soup.select('dd > p:nth-of-type(3) > span') # 地址 areas = soup.select('dd > div.area.alignR > p:nth-of-type(1)') # 面積 prices = soup.select('dd > div.moreInfo > p:nth-of-type(1) > span.price') # 總價 danjias = soup.select('dd > div.moreInfo > p.danjia.alignR.mt5') # 單價 authors = soup.select('dd > p.gray6.mt10 > a') # 發佈者 tags = soup.select('dd > div.mt8.clearfix > div.pt4.floatl') # 標籤 for title, href, detail, court, add, area, price, danjia, author, tag in zip(titles, hrefs, details, courts, adds, areas, prices, danjias, authors, tags): data = { 'title': title.get_text(), 'href': 'http://esf.xian.fang.com' + href.get('href'), 'detail': list(detail.stripped_strings), 'court': court.get_text(), 'add': add.get_text(), 'area': area.get_text(), 'price': price.get_text(), 'danjia': danjia.get_text(), 'author': author.get_text(), 'tag': list(tag.stripped_strings) } print(data)
3、調用spider_1函數爬取指定網頁
spider_1('http://esf.xian.fang.com/')
4、循環翻頁爬取二手房信息
考慮到每頁只顯示30條,總共100頁,寫一個循環調用的語句,把100頁的內容全部爬下來
# 循環,把第2-100頁全部爬下來page = 1while page < 100: url = 'http://esf.xian.fang.com/house/i3'+str(page+1) spider_1(url) page = page + 1
由於房天下的二手房信息是實時更新的,其默認排序是按照發布時間,因此在爬取過程中,會有重複的數據,如下圖,3000條數據中有523條重複(為避免重複可以嘗試倒序循環爬取)。
1.1 爬取目的
一個朋友在學習自考,作業是爬取數據進行數據分析,正好最近我在學習python,所以他委託我幫他完成這一工作
1.2使用模塊
requests進行網絡請求、bs4進行數據解析、xlwt進行excel表格存儲
2、網頁結構分析
2.1 首頁分析,獲取數據
網頁鏈接:http://sh.lianjia.com/ershoufang/pudongxinqu 紅色文字對應的是區名
[python] view plain copy
# 指定爬蟲所需的上海各個區域名稱
citys = ['pudongxinqu','minhang','baoshan','xuhui','putuo','yangpu','changning','songjiang',
'jiading','huangpu','jinan','zhabei','hongkou','qingpu','fengxian','jinshan','chongming','shanghaizhoubian']
[python] view plain copy
def getHtml(city):
url = 'http://sh.lianjia.com/ershoufang/%s/' % city
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
request = requests.get(url=url,headers=headers)
# 獲取源碼內容比request.text好,對編碼方式優化好
respons = request.content
# 使用bs4模塊,對響應的鏈接源代碼進行html解析,後面是python內嵌的解釋器,也可以安裝使用lxml解析器
soup = BeautifulSoup(respons,'html.parser')
# 獲取類名為c-pagination的div標籤,是一個列表
page = soup.select('div .c-pagination')[0]
# 如果標籤a標籤數大於1,說明多頁,取出最後的一個頁碼,也就是總頁數
if len(page.select('a')) > 1:
alist = int(page.select('a')[-2].text)
else:#否則直接取出總頁數
alist = int(page.select('span')[0].text)
saveData(city,url,alist+1)
2.2 獲取每個區的總頁數
2.3 選中一頁查看頁面鏈接規律
具體鏈接地址:http://sh.lianjia.com/ershoufang/pudongxinqu/d2
請求頁面具體數據,數據結構
3.總代碼
我用的是python2.7進行爬取的,不確定在python3之後的運行有沒有問題,建議python2版本進行嘗試
[python] view plain copy
#_*_coding:utf-8_*_
# 導入開發模塊
import requests
# 用於解析html數據的框架
from bs4 import BeautifulSoup
# 用於操作excel的框架
import xlwt
# 創建一個工作
book = xlwt.Workbook()
# 向表格中增加一個sheet表,sheet1為表格名稱 允許單元格覆蓋
sheet = book.add_sheet('sheet1', cell_overwrite_ok=True)
# 指定爬蟲所需的上海各個區域名稱
citys = ['pudongxinqu','minhang','baoshan','xuhui','putuo','yangpu','changning','songjiang',
'jiading','huangpu','jinan','zhabei','hongkou','qingpu','fengxian','jinshan','chongming','shanghaizhoubian']
def getHtml(city):
url = 'http://sh.lianjia.com/ershoufang/%s/' % city
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
request = requests.get(url=url,headers=headers)
# 獲取源碼內容比request.text好,對編碼方式優化好
respons = request.content
# 使用bs4模塊,對響應的鏈接源代碼進行html解析,後面是python內嵌的解釋器,也可以安裝使用lxml解析器
soup = BeautifulSoup(respons,'html.parser')
# 獲取類名為c-pagination的div標籤,是一個列表
page = soup.select('div .c-pagination')[0]
# 如果標籤a標籤數大於1,說明多頁,取出最後的一個頁碼,也就是總頁數
if len(page.select('a')) > 1:
alist = int(page.select('a')[-2].text)
else:#否則直接取出總頁數
alist = int(page.select('span')[0].text)
# 調用方法解析每頁數據
saveData(city,url,alist+1)
# for i in range(1,alist + 1):
# urlStr = '%sd%s' % (url,i)
# 調用方法解析每頁數據,並且保存到表格中
def saveData(city,url,page):
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
-
for i in range(1,page):
html = requests.get(url='%sd%s' % (url,i),headers=headers).content
soup = BeautifulSoup(html,'html.parser')
infos = soup.select('.js_fang_list')[0].select('li')
for info in infos:
# print '*'*50
des = info.find('a',class_="text link-hover-green js_triggerGray js_fanglist_title").text
dd = info.find('div',class_='info-table')
nameInfo = dd.find('a',class_='laisuzhou')
name = nameInfo.text # 每套二手房的小區名稱
fangL = dd.find('span').contents[-1].strip().split('|')
room_type = fangL[0].strip() # 每套二手房的戶型
-
size = fangL[1].strip() # 每套二手房的面積
if len(fangL[2].split('/')) == 2:
region = fangL[2].split('/')[0].strip() # 每套二手房所屬的區域
loucheng = fangL[2].split('/')[1].strip() # 每套二手房所在的樓層
else:
region = ''# 每套二手房所屬的區域
loucheng = fangL[2].strip() # 每套二手房所在的樓層
if len(fangL) != 4:
chaoxiang = '*'
else:
chaoxiang = fangL[3].strip() # 每套二手房的朝向
-
timeStr = info.find('span',class_='info-col row2-text').contents[-1].strip().lstrip('|')
builtdate = timeStr # 每套二手房的建築時間
# 每套二手房的總價
price = info.find('span',class_='total-price strong-num').text.strip()+u'萬'
# 每套二手房的平方米售價
jun = info.find('span',class_='info-col price-item minor').text
price_union = jun.strip()
# 一定要聲明使用全局的row變量,否則會報錯,說定義前使用了該變量
global row
# 把數據寫入表中,row:行數 第二個參數:第幾列 第三個參數:寫入的內容
sheet.write(row,0,des)
sheet.write(row,1,name)
sheet.write(row,2,room_type)
sheet.write(row,3,size)
sheet.write(row,4,region)
sheet.write(row,5,loucheng)
sheet.write(row,6,chaoxiang)
sheet.write(row,7,price)
sheet.write(row,8,price_union)
sheet.write(row,9,builtdate)
# 每次寫完一行,把行索引進行加一
row += 1
# with open('%s.csv' % city,'ab') as fd:
# allStr = ','.join([name,room_type,size,region,loucheng,chaoxiang,price,price_union,builtdate])+'\n'
# fd.write(allStr.encode('utf-8'))
# 判斷當前運行的腳本是否是該腳本,如果是則執行
# 如果有文件xxx繼承該文件或導入該文件,那麼運行xxx腳本的時候,這段代碼將不會執行
if __name__ == '__main__':
# getHtml('jinshan')
row=0
for i in citys:
getHtml(i)
# 最後執行完了保存表格,參數為要保存的路徑和文件名,如果不寫路徑則默然當前路徑
book.save('lianjia-shanghai.xls')
好了,今天的知識就分享到這裡,歡迎關注愛編程的南風,私信關鍵詞:學習資料,獲取更多學習資源,如果文章對你有有幫助,請收藏關注,在今後與你分享更多學習python的文章。同時歡迎在下面評論區留言如何學習python。
閱讀更多 愛編程的南風 的文章