江寓租房挂牌房源信息获取

背景

之前爬取的都只能算静态网页,这次的江寓却变成动态的,而动态网址主要采用了Ajax加载技术,当你翻页的时候,你会发现地址栏的url都不变​​​

何为Ajax技术

Ajax是Asynchronous JavaScript and XML的缩写,翻译成异步的 JavaScript 和 XML技术,Ajax不是新的编程语言,而是一种网页加载新方法,最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。Ajax技术的核心是XMLHttpRequest对象(简称XHR),可以通过使用XHR对象获取到服务器的数据,然后再通过DOM(Document Object Model)将数据插入到页面中呈现。虽然名字中包含XML,但Ajax通讯与数据格式无关,所以我们的数据格式可以是XML或JSON等格式。

如何破解

F12打开开发者模式,Ctrl+R刷新后点击Network,选择XHR,发现请求网页为

http://www.jiangroom.com/queryRoomsAsync?offset=0

然后回原网页点击第2页的时候,会发现

http://www.jiangroom.com/queryRoomsAsync?offset=12

可以推测offset是网页的参数,回原网页点击第3页的时候,变成了

http://www.jiangroom.com/queryRoomsAsync?offset=24

江寓租房挂牌房源信息_江寓

验证了每翻一页,offset增加12,可以推定offset为网页的偏移量,有了网页偏移量参数就可以利用来构造全部一级网页

def generate_pages(num): #构造所有一级网址
start_url="http://www.jiangroom.com/queryRoomsAsync?offset={}" #起始网址
for i in range(0,num,12): #每个offset步长为12
yield start_url.format(i)

既然能够把所以一级网页构造出来,那么就可以从一级网页进入二级网页,在二级网页抓取所需字段。

完整代码

# -*- coding: utf-8 -*-
"""
Created on Fri Aug 2 10:00:46 2019
title:jiangroom
@author: 帅帅de三叔
"""
import requests #导入网页请求模块
import time #导入时间模块
import json #导入json模块
from bs4 import BeautifulSoup #导入网页解析模块
import pymysql #导入数据框模块
header={"User-Agent":"Mozilla/5.0(Windos NT 6.1) AppleWebKit/537.36 (KHTML, like(Gecko) Chrome/75.0.3770.142 Safari/537.36)"} #构造请求头

print("start connecting database jiangroom……\n")
db=pymysql.connect("localhost","root","123456","jiangroom",charset='utf8') #链接数据库
cursor=db.cursor()#获取游标
cursor.execute("drop table if exists jiangroom_wh") #重写方式
print("start creating table jiangroom_wh in database jiangroom\n")
c_sql="""create table jiangroom_wh(
title varchar(30),
area varchar(5),
price varchar(8),
house_type varchar(8),
towards varchar(6),
floor varchar(6),
address varchar(30),
code varchar(20)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8"""
cursor.execute(c_sql) #执行建表操作
print("table jiangroom_wh has been created")

def generate_pages(num): #构造所有一级网址
start_url="http://www.jiangroom.com/queryRoomsAsync?offset={}" #起始网址
for i in range(0,num,12): #每个offset步长为12
yield start_url.format(i)

def get_items(generate_pages): #构造详情页进入详情页获取详情字段
session=requests.session() #建立请求会话
answer=session.post(generate_pages) #post发出请求
#print(answer.text)
soup=BeautifulSoup(answer.text,'lxml') #解析网页
#print(soup)
house_info=soup.find("p").get_text()#房间id值
house_info=json.loads(house_info) #jsonload将json格式转化为python的列表格式
link="http://www.jiangroom.com/roomDetail?id="
for house in house_info:
detail_url=link+str(house["id"]) #构造房源详情页
print(detail_url) #打印详情页
response=requests.get(detail_url,headers=header) #get发出请求
time.sleep(1) #进程挂起1秒
soup=BeautifulSoup(response.text,"lxml") #解析详情页
title=soup.find("div",class_="roomDetails").find("h5",class_="building").get_text() #房源名称
address=soup.find("div",class_="roomDetails").find("p",class_="address").get_text().replace("位置:","") #详细地址
price=soup.find("div",class_="roomDetails").find("span",class_="price").get_text().replace("¥","") #房价
floor=soup.find("div",class_="roomDetails").find("ul",class_="details").findAll("li")[0].find("span",class_="val").get_text().replace("层","") #楼层
area=soup.find("div",class_="roomDetails").find("ul",class_="details").findAll("li")[1].find("span",class_="val").get_text() #面积
house_type=soup.find("div",class_="roomDetails").find("ul",class_="details").findAll("li")[3].find("span",class_="val").get_text() #房型
towards=soup.find("div",class_="roomDetails").find("ul",class_="details").findAll("li")[2].find("span",class_="val").get_text() #朝向
code=soup.find("div",class_="roomDetails").find("div",class_="room_num clearfix").find("p",class_="num").find("span").get_text() #编号
print(title,code,area,price,house_type,towards,floor,address) #打印详细字段
insert_data=("INSERT INTO jiangroom_wh(title,code,area,price,house_type,towards,floor,address)""VALUES(%s,%s,%s,%s,%s,%s,%s,%s)") #控制插入格式
jiangroom_data=([title,code,area,price,house_type,towards,floor,address]) #执行插入操作
cursor.execute(insert_data,jiangroom_data) #执行插入操作
db.commit()#主动提交


if __name__=="__main__":
num=12*int(input("please input the total pages:")) #输入总的网页数,offset的步长为12
for url in generate_pages(num): #对所有的一级网页循环
get_items(url) #调用获取详情字段函数

代码解读

整个过程可以分为三步,第一步通过函数generate_pages构造出所有的一级网页,第二步通过post请求在一级网页抓取房源的id,根据房源id值字符串拼接技术 link+str(house[“id”]) 构造房源的详情页,然后进入详情页抓取所需字段,最后存入到数据库,整个过程一气呵成。

报错及解决办法

在写入mysql的时候如果报错

DataError: (1406, "Data too long for column 'community' at row 1")

可以在在mysql命令里面执行下面语句

SET @@global.sql_mode= '';

免责申明

Python爬虫仅为学习交流,如有冒犯,请告知删。

江寓租房挂牌房源信息_挂牌房源_02