爬取10w条链家租房数据

微信扫一扫,分享到朋友圈

爬取10w条链家租房数据

爬取10w条链家租房数据

一.背景

  • 因为女票的工程实践选了python数据分析,要分析北上广深的租房现状,然后我就只能扒拉一下以前的python代码,看看能不能爬个几万条数据给她分析(感觉都是老生常谈的分析了~)

  • 因为我是做前端的,所以网页数据解析使用的是 pyquery
    这个库,使用语法有点像jquery
  • pymysql
    selenium
    requests
    

二.分析

  • 以深圳为例,链家租房的网址是:https://sz.lianjia.com/zufang/ ; 从而一个个去看北上广深,得到城市数组 ['sz','sh','bj','gz']
  • 分析深圳翻页接口:https://sz.lianjia.com/zufang/pg100/#contentList;当页数大于100的时候,得到的数据还是和100页的时候一样,所以 改变pg后面的数字是无法得到所有数据的
  • 思考: 一个城市分为多个区,一个区分为多个街道之类的
    ,那么每个街道的页数上限也是100的话,那么即使偶尔有一两个超过100页的街道,得到的数据量也是远大于我们100页的数据量

三.问题

  • 在实际编码中遇到了一些问题

  • 获取到的数据中存在一定数量的广告
    :经过观察发现广告没有对应房子地址的元素,所以通过这个判断是否是广告,如果是广告则爬取下一条数据
  • 链家反爬策略
    : 链家的反爬相对来说还是很友好的,即使被抓到了,人机验证几次就又可以了,所以我这里只是通过 time.sleep()休眠方式来进行反反爬
    。有钱的朋友可以去淘宝买ip弄个ip池,这样啥反爬都不慌了,至于那些免费ip的网站基本没啥用。
  • 爬到一半结果被反爬
    :我的解决方案比较low,就是手动把csv文件中已经用到的url删除,下一次运行就去爬剩下还没爬取的数据

四.实现

  1. 首先建立数据库

  • 在navicat创建数据库lianjia,创建表的语句如下:

create table shanghai(
id int(5) PRIMARY KEY NOT NULL auto_increment,
city VARCHAR(200),
hName VARCHAR(200),
way VARCHAR(200),
address VARCHAR(200) ,
area VARCHAR(200) ,
position VARCHAR(200),
type VARCHAR(200),
price VARCHAR(200),
time VARCHAR(200),
url VARCHAR(200)
)
复制代码
  1. 获取城市的区数据

  • 首先会在首行先导入所有依赖库

from selenium import webdriver
import time
import csv
from pyquery import PyQuery as pq
import requests
import pymysql
import random
复制代码
  • 下面的获取区的代码

def getArea():
brow = webdriver.Chrome()
cityArr = ['sz','sh','bj','gz']
file = open('area.csv', 'a', encoding='utf-8', newline='')
# 打开文件,准备追加内容
writer = csv.writer(file)
for city in cityArr:
url = 'https://' + city + '.lianjia.com/zufang/'
brow.get(url)
doc=pq(brow.page_source,parser='html')
ul=doc('#filter ul').items()
# 获得区的url
for item in ul:
tem = item.attr('data-target')
if(tem == 'area'):
for li in item.items('li'):
if(li.text()!='不限'):
str = url.split('/zufang')[0] + li.children('a').attr('href')
writer.writerow(str.split(','))
time.sleep(10)
# 退出
file.close()
brow.quit()
复制代码
  1. 获取区的街道等信息

def getDetail():
# 读
arr = []
with open('area.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
arr.append(row[0])
f.close()
# 写
file_detail = open('detail.csv', 'a', encoding='utf-8', newline='')
writer_detail = csv.writer(file_detail)
brow = webdriver.Chrome()
for val in arr:
brow.get(val)
doc = pq(brow.page_source, parser='html')
ul = doc('#filter ul').items()
for i, item in enumerate(ul):
if (i == 3):
for li in item.items('li'):
if (li.text() != '不限' and li.children('a')):
str = val.split('/zufang')[0] + li.children('a').attr('href')
writer_detail.writerow(str.split(','))
print(str)
time.sleep(3)
file_detail.close()
brow.quit()
复制代码
  1. 爬取详细租房信息

def run():
with open('detail.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
time.sleep(random.randint(20,100))
pgRes = requests.get(row[0])
pgDoc = pq(pgRes.text, parser='html')
pgSum = int(pgDoc('.content__pg').attr('data-totalpage'))
pg = 0
# 还需要根据页数来进行爬取。有些再加一层循环
while(pg < pgSum):
pg+=1
url =row[0] + 'pg%d'%pg
print(url)
res = requests.get(url)
doc = pq(res.text, parser='html')
city = doc('.content__title a')[0]
str = ''
time.sleep(random.randint(2,20))
if(city.text == '深圳'):
str = 'shenzhen'
elif(city.text == '广州'):
str = 'guangzhou'
elif(city.text == '上海'):
str = 'shanghai'
elif(city.text == '北京'):
str = 'beijing'
else:
Exception('城市名称错误')
list = doc('.content__list .content__list--item').items()
for li in list:
# 需要先建立数据库,表格
db = pymysql.connect(host='localhost', user='root', password='123456', db='lianjia')
tem = li.find('.content__list--item--des')
arr = tem.text().split('/')
way = li.find('.content__list--item--title a').text().split('·')
house_data = (
city.text,
tem.children('a')[2].text if tem.children('a').length>1 else '广告',
way[0] if way[0] else '',
arr[0] if arr.__len__() > 0 else '',
arr[1] if arr.__len__() > 1 else '',
arr[2] if arr.__len__() > 2 else '',
arr[3] if arr.__len__() > 3 else '',
li.find('.content__list--item-price em').text(),
li.find('.content__list--item--time').text(),
('https://sz.lianjia.com' + li.find('.twoline').attr('href'))if(li.find('.twoline').attr('href')) else ''
)
if(house_data[1]=='广告'):
continue
# 声明游标
cursor = db.cursor()
sql = "insert into "+ str +"(city,hName,way,address,area,position,type,price,time,url)" \
"  values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
cursor.execute(sql, house_data)
db.commit()  # 提交数据库
db.close()
复制代码

五.完整代码

  • 现在写的版本还是比较那啥,反爬之后需要手动删除csv文件中的url,而且可能会有重复/遗漏的数据

  • 在博客园看到有大佬用移动端反编译的方式找到接口完成爬取,我还没试验过,但是看起来很有料,有兴趣的可以去试试:https://www.cnblogs.com/mengyu/p/9115832.html

  • 因为掘金的字数限制。所以只把最后调用的代码贴上来~

if __name__=='__main__':
getArea()
getDetail()
run()
复制代码

微信扫一扫,分享到朋友圈

爬取10w条链家租房数据

万代请来Hello Kitty协助用户守护自己的电子宠物

上一篇

你也可能喜欢

爬取10w条链家租房数据

长按储存图像,分享给朋友