在本文中以爬取某网中每个房型房源信息,并且按照房源用途分别保存到不同表中为例。
首先导入爬虫需要的selenuim模块、休眠要用的time模块、连接数据库要用的pymysql模块,并且连接数据库。
host=你本机的ip地址,localhost就是本机的ip地址
user=连接MySQL的用户名
password=连接MySQL的密码
db=操作的数据库名称
cursor为一个对象,如果需要对我们定义的数据库进行操作,直接就对cursor操作即可。
如果想要把爬取下来的数据保存到数据库表中,就必须要先创建表结构,比如在下方最后三行代码中,创建了三张表用于后续保存爬取下来的数据
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- from selenium import webdriver
- from time import sleep
- import pymysql
- # 连接数据库
- conn = pymysql.connect(host='localhost',user='root',password='123456',db='db')
- cursor = conn.cursor()
- #执行一个SQL语句
- cursor.execute('create table if not exists bk_zz(name varchar(255),sale varchar(255),type varchar(255),local varchar(255),local1 varchar(255),huxing varchar(255),jianmian varchar(255),small_price varchar(255),big_price varchar(255),subway varchar(255),shopping varchar(255))')
- cursor.execute('create table if not exists bk_bs(name varchar(255),sale varchar(255),type varchar(255),local varchar(255),local1 varchar(255),huxing varchar(255),jianmian varchar(255),small_price varchar(255),big_price varchar(255),subway varchar(255),shopping varchar(255))')
- cursor.execute('create table if not exists bk_qt(name varchar(255),sale varchar(255),type varchar(255),local varchar(255),local1 varchar(255),huxing varchar(255),jianmian varchar(255),small_price varchar(255),big_price varchar(255),subway varchar(255),shopping varchar(255))')
cursor用来执行命令的方法:
callproc(self, procname, args):用来执行存储过程,接收的参数为存储过程名和参数列表,返回值为受影响的行数
execute(self, query, args):执行单条sql语句,接收的参数为sql语句本身和使用的参数列表,返回值为受影响的行数
executemany(self, query, args):执行单挑sql语句,但是重复执行参数列表里的参数,返回值为受影响的行数
nextset(self):移动到下一个结果集
cursor用来接收返回值的方法:
fetchall(self):接收全部的返回结果行.
fetchmany(self, size=None):接收size条返回结果行.如果size的值大于返回的结果行的数量,则会返回cursor.arraysize条数据.
fetchone(self):返回一条结果行.
scroll(self, value, mode=’relative’):移动指针到某一行.如果mode=’relative’,则表示从当前所在行移动value条,如果mode=’absolute’,则表示从结果集的第一 行移动value条.
以下是该案例下爬取数据的代码,可根据实际情况去更改。
- # 实现反检测
- from selenium.webdriver import ChromeOptions
- option = ChromeOptions()
- option.add_experimental_option('excludeSwitches',['enable-automation'])
-
- # 实例化一个浏览器对象
- bro = webdriver.Chrome(executable_path='./chromedriver',options=option)
-
- # 对贝壳发起请求
- bro.get('https://bj.ke.com/')
- # 定位搜索按钮,并点击
- bro.find_element_by_xpath('//*[@id="beike"]/div[1]/div/div[2]/div/ul/li[2]/a').click()
- sleep(2)
- for x in range(10):
- # 下拉页面
- bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
- sleep(5)
- # 解析页面
- li_list = bro.find_elements_by_xpath('/html/body/div[6]/ul[2]/li')
- sleep(1)
- for li in li_list:
- goods = li.text.split('\n')
- # print(goods)
- if '新房顾问' in goods[4]:
- del goods[4]
- for z,y in enumerate(goods):
- if y == '关注':
- del goods[z]
- # print(goods)
- a = goods[1].split(' ')
- # print(a)
- # 获取小区名称
- name = a[0]
- # 获取售卖情况
- sale = a[1]
- # 获取房屋类型
- house = a[2]
-
- b = goods[2].replace(',','.').split('/')
- print(b)
- # 获取所在区
- big_add = b[0]
- # 获取房屋具体位置
- small_add = b[2]
-
- if '户型' not in goods[3]:
- goods.insert(3,'户型 暂无户型信息 建面 暂无建面信息')
- goods[3] = goods[3].replace(' / ','/').replace('/建',' 建')
- c = goods[3].split(' ')
- # print(c)
- # 获取户型
- shape = c[1]
- # 获取建面
- square = c[3]
- """'50000 元/㎡(均价)', '总价1848-2500(万/套)'"""
- if '均' not in goods[5]:
- goods.insert(5,'暂无均价')
- if '总' not in goods[-1]:
- goods.append('总价暂无总价')
- print(goods)
- d = goods[-2].split(' ')
- # avg_price = goods[-2][:9]
- # print(d)
- # 获取均价
- avg_price = d[0]
-
- # 获取总价
- sum_price = goods[-1][2:].split('(')[0]
-
- e = goods[-3].split(' ')
- # print(e)
- if '地铁沿线' in e:
- e.insert(0, '地铁沿线')
- else:
- e.insert(0, '无地铁')
- if '购物方便' in e:
- e.insert(1, '购物方便')
- else:
- e.insert(1, '无商场')
- subway = e[0]
- shopping = e[1]
- if house == '住宅':
- sql = "insert into bk_zz values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
- param = ((name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping),
- (name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping))
- cursor.executemany(sql, param)
- elif house == '别墅':
- sql = "insert into bk_bs values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
- param = ((name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping),
- (name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping))
- cursor.executemany(sql, param)
- else:
- sql = "insert into bk_qt values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
- param = ((name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping),
- (name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping))
- cursor.executemany(sql, param)
- # 点击翻页
- if x == 0:
- bro.find_element_by_xpath('/html/body/div[7]/div[2]/a[5]').click()
- sleep(3)
- elif 1 <= x <= 4:
- bro.find_element_by_xpath(f'/html/body/div[7]/div[2]/a[6+{x}]').click()
- sleep(3)
- else:
- bro.find_element_by_xpath(f'/html/body/div[7]/div[2]/a[10]').click()
- print(f'第{x+1}页爬取成功')
-
- bro.quit()
- # 提交数据,并保存到数据库中
- re = cursor.fetchall()
- conn.commit()
- cursor.close()
- conn.close()
如果需要批量的插入数据,就这样做
sql = “insert into bk_zz values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)”
每个值的集合为一个tuple,整个参数集组成一个tuple或者list
param = ((name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping),(name, sale, house, big_add, small_add, shape, square, avg_price, sum_price, subway, shopping))
使用executemany方法来批量的插入数据
n=cursor.executemany(sql,param)
需要注意的是,在所有数据插入成功后,要提交数据并且保存到数据库中!!