在本文中以爬取某网中每个房型房源信息,并且按照房源用途分别保存到不同表中为例。

首先导入爬虫需要的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)

需要注意的是,在所有数据插入成功后,要提交数据并且保存到数据库中!!

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐