1. 程式人生 > >爬蟲學習之路(二)

爬蟲學習之路(二)

這次的爬蟲程式,依然沒有用框架。。

目標是爬取房天下新房和二手房網頁中的房屋資訊,如地址、面積、單價、座標等,鑑於新手房前端頁面比較混亂(我發現的頁面就有三種,相應的寫了三套方案),我的程式碼寫的也就比較混亂,所以接下來我只記錄二手房的爬取過程及程式碼。

房天下二手房的頁面如下,上面是選擇條件,下面是房源列表


房源列表中最多隻能顯示100頁,其他的會被捨棄,也就是說,如果要得到完整的資料,我們要確保房屋列表中的房子不多於100頁。我採取的方法是點進區域最小的分類,然後遍歷每個區域。


我的爬蟲的爬取路徑概括起來說就是:進入區頁面(鼓樓)-->爬取到區下一級分類的頁面連結列表(北京西路等頁面的連結)-->進入二級分類頁面(北京西路等)-->爬取房屋列表中每個房子詳細頁面的連結-->進入詳細頁面爬取地址單價等資訊

思路講完了,貼程式碼

fangtx_ershou.py

import requests
from bs4 import BeautifulSoup
from lxml import etree
import time
import os,sys
from detail import get_page_detail
import pymysql

#網頁的請求頭
header={
	'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36'
}

def get_erji_url(url):
	response=requests.get(url,headers=header)
	if response.status_code==200:
		soup=BeautifulSoup(response.text,'lxml')
		sel=etree.HTML(response.text)

		#獲取區下一級分類的url列表
		erji_url_list=sel.xpath('//p[@id="shangQuancontain"]/a/@href')

		print(erji_url_list)
		#for erji_url in erji_url_list:
		for index in range(1,len(erji_url_list)):
			time.sleep(0.5)
			print(erji_url_list[index],"\n\n")
			houzhui=str(erji_url_list[index])
			url="http://esf.nanjing.fang.com"+houzhui
			print(url,'\n\n')
			get_info(url)

def get_info(url):
	response=requests.get(url,headers=header)

	#通過BeautifulSoup進行解析出每個房源詳細列表並進行列印
	soup=BeautifulSoup(response.text,'lxml')

	#此列表中包括每個房屋欄的所有資訊
	result_li=soup.find_all('dl',{'class':'list rel'})

	#連線database
	conn=pymysql.connect(host="",port=3306,user="",password="",database="",charset="utf8")
	#得到一個可以執行SQL語句的游標物件
	cursor=conn.cursor()

	#將當前網頁抓到的連結寫入檔案,with語句會自動close()已開啟檔案
	with open(r"F:\python\python_code\files\fang_url.txt","w") as file:
		#從房源列表中獲取有用的連結等資訊
		for i in result_li:
			try:
				time.sleep(0.2)
				page_url=str(i)		
				#通過xpath獲取房屋連結和地址
				sel=etree.HTML(page_url)
				result_href=sel.xpath('//dd/p[@class="title"]/a/@href')[0]
				loupan_address=sel.xpath('//dd/p[@class="mt10"]/span/@title')[0]

				print("房子連結:"+"http://esf.nanjing.fang.com/"+result_href)
				print("房子地址:"+loupan_address)
				file.write("http://esf.nanjing.fang.com/"+result_href+'\n\n')

				#詳細頁面的函式呼叫
				[loupan_name,wuye_type,price,building_type,house_type,x,y,pic_url,region,area,district]=get_page_detail("http://esf.nanjing.fang.com/"+result_href)
				print(loupan_name,loupan_address,wuye_type,price,building_type,house_type,x,y,pic_url,region,area,district)
				print('\n\n')
			except:
				continue

			#入庫
			#定義要執行的sql語句
			sql="INSERT IGNORE INTO tb_loupan_detail_ershou(loupan_name,loupan_address,wuye_type,price,building_type,house_type,jingdu,weidu,pic_url,region,area,district) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
			try:
				#執行SQL語句
				cursor.execute(sql,[loupan_name,loupan_address,wuye_type,price,building_type,house_type,x,y,pic_url,region,area,district])
				#提交事務
				conn.commit()
			except Exception as e:
				#有異常,回滾事務
				#conn.rollback()
				continue
	#關閉游標物件
	cursor.close()
	#關閉資料庫連線
	conn.close()

	#進行下一頁的爬取
	result_next_page=soup.find('a',{'id':'PageControl1_hlk_next'})
	print(soup.find('a',{'id':'PageControl1_hlk_next'}),"\n\n")
	if result_next_page:
		aaaaaaa=0
		#函式進行遞迴
		get_info('http://esf.nanjing.fang.com/'+result_next_page.attrs['href'])
	else:
		print('沒有下一頁了')



if __name__ == '__main__':
	qu_list=['/house-a0265/','/house-a0268/','/house-a0270/','/house-a0264/','/house-a0267/','/house-a0271/','/house-a0272/','/house-a0263/','/house-a0269/','/house-a0274/','/house-a0275/','/house-a013046/']
	region_list=['鼓樓','江寧','浦口','玄武','建鄴','棲霞','雨花','秦淮','六合','溧水','高淳','南京周邊']
	#更改至f盤相應路徑下
	path="f:/ershoufang"
	os.chdir(path)
	'''獲得當前路徑
	'''
	cwd=os.getcwd()
	print(cwd)
	file_list=os.listdir()
	print(file_list)
	print("\n")
	for i in qu_list:
		url='http://esf.nanjing.fang.com'+i
		print(url)
		index=qu_list.index(i)
		region=region_list[index]
		print(region)
		#try:
		file_name=i.replace("/","")+".txt"
		print(file_name)
		if file_name in file_list: 
			print("抓取開始")
			get_erji_url(url)
			os.remove(file_name)
		#except:
			#continue
detail.py
import requests
from bs4 import BeautifulSoup
from lxml import etree
import re

#網頁的請求頭
header={
	'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36'
}


def get_page_detail(url):
	response=requests.get(url,headers=header)
	if response.status_code==200:
		soup=BeautifulSoup(response.text,'lxml')
		sel=etree.HTML(response.text)

		#獲取詳細資訊
		loupan_name=sel.xpath('//*[@id="agantesfxq_C03_05"]/text()')
		if len(loupan_name):
			loupan_name=loupan_name[0]
		#print(loupan_name)
		wuye_type=sel.xpath('//div[@class="w1200 clearfix"]/div[1]/div[1]/div[2]/div[4]/span[2]/text()')
		if len(wuye_type):
			wuye_type=wuye_type[0].strip()
		#print(wuye_type)
		price=sel.xpath('//div[@class="trl-item1 w132"]/div[@class="tt"]/text()')
		if len(price):
			price=price[0].strip()
		#print(price)
		building_type="二手房"
		#print(building_type)
		house_type=sel.xpath('//div[@class="trl-item1 w146"]/div[@class="tt"]/text()')
		if len(house_type):
			house_type=house_type[0].replace("\r", "").replace("\n", "").replace("\t", "").strip()
		#print(house_type)
		map=sel.xpath('//div[@class="zf_new_left floatl"]/script/text()')[0]
		patx = 'pageConfig.x=\'(.*?)\';'
		x=re.findall(patx,str(map),re.S)[0]
		paty='pageConfig.y=\'(.*?)\';'
		y=re.findall(paty,str(map),re.S)[0]
		#print(x)
		#print(y)
		pic_url=sel.xpath('//*[@id="bigImgBox"]/div[1]/img/@src')
		if len(pic_url):
			pic_url=pic_url[0]
		#print(pic_url)
		diqu=sel.xpath('//*[@id="address"]/a/text()')
		if len(diqu):
			region=diqu[0].strip()
			district=diqu[1].strip()
		area=sel.xpath('//div[@class="trl-item1 w182"]/div[@class="tt"]/text()')
		if len(area):
			area=area[0]
		#print(area)
		return loupan_name,wuye_type,price,building_type,house_type,x,y,pic_url,region,area,district

if __name__ == '__main__':
    # url連結
    url = 'http://esf.nanjing.fang.com/chushou/3_165137745.htm'
    # 頁面爬取函式呼叫
    get_page_detail(url) 

爬太快的話會被網站禁ip,所以每爬一條需要休眠0.2秒,速度很慢