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

背景

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

何为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爬虫仅为学习交流,如有冒犯,请告知删。

延申阅读
青客公寓挂牌房源分城市爬取
优客逸家挂牌房源爬取
建方公寓挂牌房源信息爬取

扫描二维码关注公众号,回复: 8986110 查看本文章
发布了45 篇原创文章 · 获赞 12 · 访问量 8677

猜你喜欢

转载自blog.csdn.net/zengbowengood/article/details/98942714