码农日记

薄洪涛的个人博客

python爬虫第二篇之安居客

最近考虑换个环境,打算去租个房子,但是租房信息那么多,我们能不能把它爬取下来做个统计,看看什么价位的房子最多,哪个地段的房子最便宜呢

在爬取之前,请大家安装下BeautifulSoup库和requests库还有pymysql库
安装方法有两种:

1、cmd中pip install + 库名安装

1.jpeg

2、pycharm中File-setting-project-InterPreter,按照下图所示安装就可以了

2.jpeg

安装BeautifulSoup如果你是python3,请选择安装BeautifulSoup4
解释下这几个库的作用:
Requests只要是做模拟请求
BeautifulSoup主要是做解析,把requests请求的response根据你指定的规则去解析
Pymysql是保存数据用的,这里我们保存数据使用的是mysql,如果不想保存在mysql中可以不安装这个库,比如保存excel中,需要安装csv库,这里就不多说了
我们这次爬取的网站是安居客,打开网站-点击租房-本地
我们看到一大波房源,
此时的连接
https://jn.zu.anjuke.com/?from=navigation
点击下一页
https://jn.zu.anjuke.com/fangyuan/p2/
再下一页
https://jn.zu.anjuke.com/fangyuan/p3/
发现规律了没,第几页就是P几对不对
那第一页呢,我们试试p1,
https://jn.zu.anjuke.com/fangyuan/p1/
发现这个url和https://jn.zu.anjuke.com/?from=navigation是同一个页面

所以我们要拼接的url现在已经很明确了,只需要使用for循环就可以啦,看代码

from bs4 import BeautifulSoup
import requests
import pymysql.cursors
 
class Spilser:
base_url = "https://jn.zu.anjuke.com/fangyuan/p"
def getRoom(self):
     for i in range(1,50):
          url = self.base_url+str(i)+"/"
          print("访问的url"+url)
spider = Spilser()
spider.getRoom()

前3行就不用说了吧,就是导入下我们安装的类库
第5行,我们声明了一个爬虫的类,然后一个base_url成员变量,一个getRoom方法,在里面for循环,输出1到50页房源的url,这里可以打印下,看看url是否正确
是不是炒鸡简单?
我们继续
拿到每一页的链接之后怎么做?当然是请求这些链接啦,我们使用requests来请求,看代码


from bs4 import BeautifulSoup
import requests
import pymysql.cursors
 
class Spilser:
base_url = https://jn.zu.anjuke.com/fangyuan/p
headers = {
    'Connection': 'keep-alive',
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9'
}
 
def getRoom(self):
    for i in range(1,50):
        url = self.base_url+str(i)+"/"
        print("访问的url"+url)
        response = requests.get(url,headers=self.headers).text
rooms = BeautifulSoup(response,'lxml').findAll('div',class_='zu-itemmod')
response就是我们请求后服务器返回给我们的数据(可以理解为我们看到的页面)
这里要划重点!!
请求的时候最好加上头信息,让我们的程序请求更像浏览器发出的。
我们使用chrome的控制台(啥?你不知道控制台怎么看?F12啊)看到每个房源信息都是由一个class=‘zu-itemmod’的div,所以我们使用BeautifulSoup的findAll方法去查找指定的class,我们得到的rooms就是一页中所有的房源信息,可以打印下(调试的时候,可以把for循环调成2页就好了)


3.jpeg

这是返回的结果


4.jpeg


因为rooms是多个房源信息,所以我们要对它进行遍历,代码如下
for room in rooms:
    # print(room)
    # 标题
    title = room.find('div',class_='zu-info').find('h3').find('a')['title']
    # 房间基本信息
    room_info  = room.find('p',class_='details-item tag').get_text().strip().split('|')
    room_num = room_area = room_level = room_owner = ''
    if len(room_info)==3:
        room_num = room_info[0]
        room_area = room_info[1]
        room_level = room_info[2].split('\ue147')[0]
        room_owner = room_info[2].split('\ue147')[1]
    if len(room_info)==4:
        room_num = room_info[0]
        room_area = room_info[1]
        room_level = room_info[2]
        room_owner = room_info[3]
    # 出租方式
    type = room.find('span',class_='cls-1').get_text()
    # 朝向
    toward = room.find('span',class_='cls-2').get_text()
    # 价格
    price = room.find('div',class_='zu-side').find('p').get_text()
解释下上面的几个函数,
get_text()就是去除标签中的文本信息
find()就是找单个标签,可以加特定的条件,比如class来限制
strip()去掉字符串左右的空格
split()按照指定的字符进行分隔
为什么要判断len(room_info) 呢,因为room_info可能会有缺省,比如不写楼层,长度就是3了,还有可能等于2,这里就不再完善了,这篇博文的重点是教大家如何去请求和解析数据,理解了这两块,问题就不大了
这样我们就拿到了基本的数据,现在要做的就是怎么保存数据到mysql
先定义我们数据库的基本信息
MYSQL_HOSTS = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_PASSWORD = ''
MYSQL_PORT = '3306'
MYSQL_DB = 'room'
MYSQL_CHARACTERS = 'utf8'
然后写一个入库的方法
def save_data(self,title,room_num,room_level,room_area,room_owner,type,toward,price):
    # 获取游标
    connect = pymysql.Connect(user=self.MYSQL_USER, password=self.MYSQL_PASSWORD, host=self.MYSQL_HOSTS, database=self.MYSQL_DB,charset=self.MYSQL_CHARACTERS)
    cur = connect.cursor()
    sql = "INSERT INTO room (id,title,room_num,room_area,room_level,room_owner,type,toward,price) VALUES ( '%s', '%s', '%s' ,'%s', '%s', '%s', '%s', '%s','%s')"
    value = ('0', title, room_num, room_area,room_level, room_owner, type,toward,price)
    cur.execute(sql % value)
    connect.commit()
这里需要注意的是,如果你把主键id设置成自增的话,一定要把id的value设置成0,而不是null
下面就是我们爬去下来的数据了


5.jpeg

接来下就是大家结合图表工具做可视化,这里就不必详述;本次的代码我已经传到github,传送门在此


  • 评论列表
  •  薄洪涛
     发布于 2018-10-24 09:31:04  回复该评论
  • 由于安居客网站可能会更新,代码可能不会适用,请大家理解思路就可以

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权所有 | 转载请标明出处