爬虫项目六:用Python爬下链家新房所有城市近三万条数据


前言

本文全面解析了链家新房源数据,爬取了全部城市的房源信息,共两万六千条数据


提示:以下是本篇文章正文内容,下面案例可供参考

一、分析url

这个url的构成很简单,https://后面是城市的首字母 pg后表示页数。我们为了拿到所有城市的房源数据,需要构造出准确无误的所有url 有了url利用request进行访问

现在我们有两个部分是必须要获取的 一个是拿下所有城市的首字母,一个是拿下对应城市的页数

https://bj.fang.lianjia.com/loupan/pg1/

这样的话问题就来了,去哪里获取城市的首字符和对应的页数呢,我们打开他的首页看一看,点击圈中的按钮之后就会出现所选的城市,我们可以通过这些城市拿到对应的首字母
在这里插入图片描述
我们右键检查元素,每个城市对应的就是每个城市房源数据的url,我们拿到他们的url提取出首字符就可以了
在这里插入图片描述
现在有了首字符,还缺对应城市的页数,我的方法是利用selenium访问每个url然后拿到他们的总页数

每个页数对应一个a标签,当存在两个及两个以上页数时我们那他倒数第二个a标签(有下一页按钮)
当仅仅只有一页时我们就直接让他等于1(没有下一页按钮)
在这里插入图片描述
在这里插入图片描述

二、拼接url

根据上文我们有了思路现在我们就去实现代码

1.实例化chrome

基本配置

代码如下(示例):

chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')  #设置无头浏览器
prefs = {'profile.managed_default_content_settings.images': 2}
chrome_options.add_experimental_option('prefs', prefs) # 禁止图片加载,加快速度
bro = webdriver.Chrome(options=chrome_options)#实例化对象
})

2.获取首字符、page

先顺顺思路,我们进入页面之后要干啥

获取首字符
进入界面
点击城市按钮
点击每一个城市
点击筛选
获取页数

我们在点击城市按钮后出现了城市列表 获取城市首字符,在我们点击第三步筛选后我们获取最大页数
在这里插入图片描述
有了这个思路现在我们写代码

打开网页 定位所有城市列表
在这里插入图片描述

bro.get('https://bj.fang.lianjia.com/')#打开网页
#城市列表
li_list=bro.find_elements_by_xpath("/html/body/div[3]/div[3]//a")

定位每个元素循环点击,点击 --》点击筛选 --》退回 --》点击

因为每次退回主页页面重新的刷新,所以每次循环最后在从新获取li_list

获取最大页数的代码位置一定要在指定的位置,只有切换到房源页是才能找到最大页数

for i in range(len(li_list)): 
	bro.find_element_by_xpath("/html/body/div[1]/div/div[1]/a[2]").click()  # 点击城市按钮
    li_list[i].click() #点击城市
    
	#在这获取页面首字符
	
    bro.find_element_by_xpath('//div[@data-search-position="search_result"]').click() #点击筛选
    ws = bro.window_handles # 当前所有页面
    bro.switch_to.window(ws[1])  # 切换新页面,房源页

	#在这获取最大页数,并保存数据

    bro.close() #关闭房源页
    bro.switch_to.window(ws[0]) # 回到主页
    li_list=bro.find_elements_by_xpath('/html/body/div[3]/div[3]//a')   		

页面首字符代码,我还多加了一个城市名称

 dic["city"]=li_list[i].get_attribute("href").replace(".fang.lianjia.com/","").replace("https://","") # 城市首字母
 dic["city_name"]=li_list[i].text #每个城市

最大页数、保存数据代码

当数据存在多个页数时是有“下一页”这个按钮的,当只有一页时是不存在“下一页”按钮,以此判断页数,最后边爬边保存

 if "下一页" in bro.page_source:
     dic["page"]=bro.find_element_by_xpath('//div[@class="page-box"]/a[last()-1]').text #最多页数
 else:
     dic["page"]="1"
 with open(".//city_page.csv", "a", encoding="utf-8") as f:
     writer = csv.DictWriter(f, dic.keys())
     writer.writerow(dic)

3.拼接url

我们获取了最大page、和首字符现在开始拼接url

names=["city","name","page"]
df=pd.read_csv("city_page.csv",names=names)  #读入数据
df.page=df.page.map(lambda x:re.findall("(\d+)",str(x))[0])  #提取出页数
for a, b in zip(df.city, df.page):
    for i in range(int(b)):
        url = "https://%s.fang.lianjia.com/loupan/pg%d/" % (a, i+1)  #拼接url
        #保存url为txt
        with open("urls.txt","a",encoding="utf-8") as f:
            f.write(url)
            f.write("\n")

到此为止,所有城市的url全部拼接完毕,一共有2669条url,有了这些 我们就可以用requests多线程快速的爬取数据了

三、获取房源数据

有了url,现在我们来解析一下页面数据,我们要拿下名称、地址、价格、类型等等数据

在这里插入图片描述
右键检查元素我们知道,房源数据都在ul标签的li标签里,每一个li对应一个房源

在这里插入图片描述
这样我们就可以利用Xpath定位获取数据,代码没有加try 应该加上try 因为有的数据在列表中是不存在的

li_list=html.xpath('//ul[@class="resblock-list-wrapper"]/li')
for li in li_list:
    dic={}
    dic["title"]=li.xpath('./div//div[@class="resblock-name"]/a/text()')[0]
    dic["type"]=li.xpath('./div//span[@class="resblock-type"]/text()')[0]
    dic["status"]=li.xpath('./div//span[@class="sale-status"]/text()')[0]
    dic["location"]=''.join([x for x in li.xpath('./div//div[@class="resblock-location"]//text()') if '\n' not in  x])
    dic["room"]=''.join([x for x in li.xpath('./div//a[@class="resblock-room"]//text()') if '\n' not in  x])
    dic["area"]=li.xpath('.//div[@class="resblock-area"]/span/text()')[0]
    dic["tag"]=''.join([x for x in li.xpath('./div//div[@class="resblock-tag"]//text()') if '\n' not in  x])
    dic["main_price"]=li.xpath('./div//div[@class="main-price"]/span[@class="number"]/text()')[0]
    dic["price"]=li.xpath('./div//div[@class="resblock-price"]/div[@class="second"]/text')[0]
    dic["img_link"]=li.xpath('./a//img[@class="lj-lazy"]/@src')[0]

location、area、tag三个数据获取到的都是列表所以在获取时剔除掉无用字符,并且连接为字符串

''.join([x for x in li.xpath('./div//div[@class="resblock-tag"]//text()') if '\n' not in  x])

list=[]
for x in li.xpath('./div//div[@class="resblock-tag"]//text()'):
	if "\n" not in x:
		list.append(x)
''.join(list)

读取url 因为我们上步已经保存了url为txt 现在我们读入url

urls = open("urls.txt", "r", encoding="utf-8").read()
urls=urls.split("\n")[:-1] #根据换行符分割 转换为列表

保存数据,这个应放在循环li_list中,边爬边存

with open(".//fangyuan.csv", "a", encoding="utf-8") as f:
    writer = csv.DictWriter(f, dic.keys())
    writer.writerow(dic)

最后可以开启线程池快速的爬取数据

 pool = Pool(4)
 pool.map(parser_data,urls)

采集完成之后看一下效果,有5MB多
在这里插入图片描述
去重之后数据有将近3W条,10个字段

在这里插入图片描述
到这里这篇文章就结束了,如果你对爬虫有兴趣,可以关注我的主页 近期再写一些爬虫项目,主页中已经更新了多个爬虫。

本文章用到的代码在公众号“阿虚学Python”中回复“链家”获取,还有更多爬虫项目等你来看哦
在这里插入图片描述
谢谢大家的观看,如果觉得这篇文章不错就点个赞支持一下吧👍

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值