Python程序员如果买房,应当有一个自己收集房价数据,再进行数据分析的过程。我尝试了用47行代码下载网站的房价数据,并导出到可用EXCEL打开的CSV文件,填了许多坑,有兴趣的可以继续看啦。
先放上程序设计思路的简单的思维导图。
获取网页内容
1、导入requests库。
import requests
2、设置参数
用for循环进行代码实现。(为了减轻服务器的负载,翻页之前要暂停5秒钟):
for i in range(1,3):
link='https://guangzhou.anjuke.com/sale/dongchuan/p'+str(i)+r'/#filtersort'
import time
time.sleep(5)
print ('page'+str(i))
2) 定制请求头:
有的网站,如果没有定制请求头,在网络爬取数据时,就不返回正确的结果。
在Google Chrome浏览器中,点击“视图---开发者---开发者工具”,打开开发者工具视图。在地址栏输入网址并且按回车键,在开发者工具视图中,单击“Network”选项,单击左边Namer的方框中找到请求的网页,,在右边的Headers方框中,可以找到Response Headers的详细信息,其中可以找到Request Headers的详细信息,再找到user-agent的详细信息:Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36复制并粘贴到代码中。
headers={'User-Agent':'Mozilla/5.0(Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/67.0.3396.79 Safari/537.36'}
3)自定义等待超时时间
有时服务器长时间不响应,爬虫程序会一直等待。为解决此问题,可以设定timeout的参数值,意思是如果服务器在设定的秒数内不应答,就返回异常。
timeout=20
3、使用requests库来发送http请求。
r=requests.get(link,headers=headers,timeout=20)
解析网页数据
1、导入BeautifulSoup库,并且用lxml HTML解析器。
from bs4 import BeautifulSoup
soup=BeautifulSoup(r.text,'lxml')
2、查看网页源代码,并定位网页各个元素所在的地址。
在Google Chrome浏览器中,点击“视图---开发者---开发者工具”,打开开发者工具视图,单击左上角的“Select an element in the page to inspect it“,
1)取得多条房屋数据:
再用鼠标移到某条房屋数据旁边,会提示 ”li.list-item“然后在开发者工具视图中,找到”Elements“选项卡,可以查看对应的html代码
用find_all函数编码如下:
house_list=soup.find_all('li',class_="list-item")
2) 取得房屋的明细数据
用上述方法,分别提取各项房屋明细数据
把数据存入二维列表
1、 把同一个房屋的明细数据,加入一条字典,并且显示在屏幕上。(每条字典记录,对应一条房屋数据。)
dic={'house_name':housename,'total_price':totalprice,'unit_price':unitprice,'no_of_rooms':noofroom,'house_area':housearea,'house_floor':housefloor,'hourse_year':houseyear,'house_broker':housebroker,'house_address':houseaddress,'hourse_tag':housetags}
print (dic)
2、 把每条房屋数据(就是每个字典记录)加入到房屋列表中
csv_house_list=[]
csv_house_list.append(dic)
把列表
倒出
到CSV文件
1、 引入pandas模块
import pandas as pd
2、 用列表生成pandas模块中的dataframe对象
df = pd.DataFrame(csv_house_list)
print (df)
3、 通过dataframe对象中的to_csv方法导出csv文件
df.to_csv("house_list.csv",encoding="utf-16",sep="\t")
完整的Python源代码,共47行
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jun 9 06:12:38 2018
@author: wupeng
"""
import requests
import time
from bs4 import BeautifulSoup
import pandas as pd
headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36'}
csv_house_list=[]
for i in range(1,3):
link='https://guangzhou.anjuke.com/sale/dongchuan/p'+str(i)+r'/#filtersort'
r=requests.get(link,headers=headers,timeout=20)
soup=BeautifulSoup(r.text,'lxml')
house_list=soup.find_all('li',class_="list-item")
for house in house_list:
housename=house.find('div',class_="house-title").a.string.strip()
totalprice=house.find('span',class_="price-det").get_text()
unitprice=house.find('span',class_="unit-price").get_text()
noofroom=house.find('div',class_="details-item").span.string.strip()
housearea=house.find('div',class_="details-item").contents[3].string.strip()
housefloor=house.find('div',class_="details-item").contents[5].string.strip()
houseyear=house.find('div',class_="details-item").contents[7].string.strip()
housebroker=house.find('span',class_="brokername").get_text()
housebroker=housebroker.replace('\\ue147','')
houseaddress=house.find('span',class_="comm-address").get_text()
houseaddress=houseaddress.replace('\\xa0','')
houseaddress=houseaddress.replace('\n','')
houseaddress=houseaddress.replace(' ','')
housetaglist=house.find_all('span',class_='item-tags')
housetags=[i.get_text() for i in housetaglist]
dic={'house_name':housename,'total_price':totalprice,'unit_price':unitprice,'no_of_rooms':noofroom,'house_area':housearea,'house_floor':housefloor,'hourse_year':houseyear,'house_broker':housebroker,'house_address':houseaddress,'hourse_tag':housetags}
print (dic)
csv_house_list.append(dic)
time.sleep(5)
print ('page'+str(i))
df = pd.DataFrame(csv_house_list)
print (df)
df.to_csv("house_list.csv",encoding="utf-16", sep="\t")
曾经踩过的坑
1、数据排列混乱
刚开始曾发现有数据排列混乱的现象,这一行的数据排到上一行去了。经过排查,发现原因是,最早使用列表来收集各个房屋的明细数据,但是有的明细数据是空值,后面的明细数据就会占据了原来空值部分的明细数据的位置,于是就乱套了。解决方法是,用字典而不是列表来收集房屋明细数据,通过字典的key-value匹配的方式,再也不担心空值数据的位置被下个数值占据的问题了。
2、CSV文件乱码
曾经试过导出到CSV文件乱码的现象,后来搜索得知,通过dataframe对象中的to_csv方法导出csv文件,需要把编码设为utf-16的格式,如果用默认的utf-8的编码就会乱码。
df.to_csv("house_list.csv",encoding="utf-16",sep="\t")