[Python] Python爬虫 抓取51job职位信息存储到excel和mysql 的代码编写及首次优化始末

目录

需求:

初版:

初版代码review:

优化:

首次优化后代码:


需求:

        编写函数,可以指明抓取某职位以及页数实现抓不同职位时(用正则和request),存到同一个excel中的不同sheet中,并将数据存到mysql中

初版:

        以下是第一次编写代码时的思路

[Python] Python爬虫 抓取51job职位信息存储到excel和mysql 的代码编写及首次优化始末_第1张图片

#编写正则
def getjobname(jobname,startnum,endnum):
    allresult=[]
    jobname1=request.quote(request.quote(jobname))
    for i in range(startnum,endnum):
        print('正在抓取第',i,'页')
        url='https://search.51job.com/list/000000,000000,0000,00,9,99,'+jobname1+',2,'+str(i)+'.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=4&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='
        response=request.urlopen(url)
        html=response.read().decode('gbk')
        #编写正则用来提取信息,去掉的东西都用.*?来代替
        reg=re.compile('',re.S)
        result=re.findall(reg,html)
        allresult+=result

         这里对jobname进行了解码处理,将函数执行时输入的汉字职位转化为匹配51job代码的值

 #存储到xls:
    if os.path.exists('51job职位信息.xlsx'):
        workbook = load_workbook("51job职位信息.xlsx")
        sheetNames = workbook.sheetnames
        if jobname in sheetNames:
            print("sheetName 重复")
            return
        else:
            sheet=workbook.create_sheet(jobname,len(sheetNames)+1)
            sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
            for each in allresult:
                sheet.append(each)

    else:
        workbook=Workbook()
        sheet=workbook.active
        sheet.title=jobname
        sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
        for each in allresult:
            sheet.append(each)

    workbook.save('51job职位信息.xlsx')

#存储到mysql
    connection = pymysql.connect(
        host='localhost',
        user='root',
        password='1234',
        db='jobinfo',
        charset='utf8'
    )
    cursor = connection.cursor()

    for index, each in enumerate(allresult):
        sql = "insert into info values " + str((index + 1,) + each) + ";"

        cursor.execute(sql)
        connection.commit()

    cursor.close()
    connection.close()


getjobname('前端开发', 1, 3) #执行函数

代码编写完成后试运行,正常。

将代入‘前端开发’的函数二次运行后,提醒“sheetName 重复”,正常。

更改jobname参数为‘人工智能’再次运行,mysql 报错:

OK,代码编写不严谨的问题来了!

初版代码review:

1.将爬虫、excel存储、mysql存储所有功能写到一起,大大降低了代码的再重复利用,一个函数最好只做一件事,改!

2.excel存储部分代码写的重复繁冗,可做精简,改!

3.思维不严谨,忽略了存储过程中的多种可能性,改!

优化:

[Python] Python爬虫 抓取51job职位信息存储到excel和mysql 的代码编写及首次优化始末_第2张图片

        重新理了下思路,对步骤做了细化,看起来严谨了一些。

#编写函数获取网页源码
from  urllib import request

def gethtml(Jobname,StartNum,EndNum):
    job = request.quote(request.quote(Jobname)) # 将输入的Jobname参数汉字转码
    for i in range(StartNum,EndNum):
        print('正在抓取第',i,'页') # 输出一个小提示,告知在打印第几页
        url='https://search.51job.com/list/000000,000000,0000,00,9,99,'+job+',2,'+str(i)\
            +'.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=' \
             '99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=' \
             '-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='
        response=request.urlopen(url)
        html=response.read().decode('gbk') # 获取网页字符串 html
        print(html)  # 打印,查看验证函数运行结果
        return html
    
gethtml('数据分析',1,2) #函数运行
#编写正则,提取网页内容
import re

def getdata(Jobname,StartNum,EndNum):
    allresult=[]
    for i in range(StartNum,EndNum):
        html=gethtml(Jobname,StartNum,EndNum) # 通过运行源码函数获取html
        # 编写正则用来提取信息,去掉的东西都用.*?来代替
        reg = re.compile('',re.S)
        result=re.findall(reg,html) # 获得一页的内容
        allresult+=result  # 通过循环,将获得的每一页内容添加到allresult中
        print(allresult)
    return allresult

getdata('数据分析',1,2)

 

#存储到excel

from openpyxl import Workbook
from openpyxl import load_workbook
import os

def savetoexcel(Jobname,StartNum,EndNum):
    data=getdata(Jobname,StartNum,EndNum) # 获取上面爬取的所有数据
    #判断文件是否存在
    if os.path.exists('51job职位信息.xlsx'):
        workbook=load_workbook('51job职位信息.xlsx')
        sheetnames = workbook.sheetnames # 获取51job职位信息.xlsx的所有sheet名
        #判断sheetname是否存在
        if Jobname in sheetnames:
            sheet=workbook[Jobname]
            values=list(sheet.values) # 获取sheet 的所有内容
            non_repeat=list(set(data).difference(set(values))) # 找出data与excel的不重复数据
            for each in non_repeat:
                sheet.append(each) # 将不重复数据写入
                #这里有个小BUG,如果数据里有一个值为空,例:'薪资'为空,则代码不断run出该条数据为不重复数据,会重复写入,需要改进(其他正常)


        else:
            sheet=workbook.create_sheet(Jobname)
            sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
            for each in data:
                sheet.append(each)
    else:
        workbook=Workbook()
        sheet=workbook.active
        sheet.title=Jobname
        sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
        for each in data:
            sheet.append(each)

    workbook.save('51job职位信息.xlsx')

savetoexcel('IT',1,2)

 

#存储到mysql

import pymysql

def savetomysql(Jobname,StartNum,EndNum):
    connection = pymysql.connect(
        host='localhost',
        user='root',
        password='1234',
        db='jobinfo',
        charset='utf8'
    )
    cursor=connection.cursor()
    # 如果数据表不存在,则执行建表,这里表名用的是中文表名
    cursor.execute('create table if not exists '+Jobname+\
        '(id int(11) primary key auto_increment,' \
        'jobname varchar(100) not null,' \
        'company varchar(100) not null,' \
        'address varchar(50),' \
        'salary varchar(50),' \
        'ptime varchar(50))' \
        'default charset utf8;')
    cursor.execute('select jobname,company,address,salary,ptime from '+Jobname)
    connection.commit()
    all = cursor.fetchall()#获取数据表的数据
    length = len(all)#获取数据表的最后一个id
    count = 0
    data=getdata(Jobname,StartNum,EndNum)# 获取爬取的数据
    for each in data:
        if each not in all: # 确定要写入的数据不在数据表内
            count+=1
            sql='insert into '+Jobname+' values '+str((count+length,)+each)+';'
            cursor.execute(sql)
        connection.commit()

    cursor.close()
    connection.close()

savetomysql('数据分析',5,7)
#这里有个小bug,函数执行时,如果第一次执行和第二次执行,没有更改StartNum,则不会写入新数据(其他正常)

        分步骤写完了第一次优化的过程,还有很多改进的地方,最明显的就是代码验证时发现的两个bug。

        还有一些地方写法感觉复杂了,有时间的话再优化。

        看了网上的帖子,对于同样的表名再次写入数据的时候很多都是用remove原表重新写入的方式,这里没有用这个方法。因为考虑到如果是工作中有人用了原本的数据,再次写入时新数据覆盖原数据,会导致调用数据的人源数据异常,所以我这里用的是查重写入的方式。

        其实可以不用做查重这一步,数据重复写入可以通过后期清洗处理。这里仅做练习用。

首次优化后代码:

完整代码整理如下:

import time
import random
import re
from  urllib import request
from openpyxl import Workbook
from openpyxl import load_workbook
import os
import pymysql

#编写函数获取网页源码
def gethtml(Jobname,StartNum,EndNum):
    job = request.quote(request.quote(Jobname)) # 将输入的Jobname参数汉字转码
    for i in range(StartNum,EndNum):
        time.sleep(random.choice([2,3,4]))
        print('正在抓取第',i,'页') # 输出一个小提示,告知在打印第几页
        url='https://search.51job.com/list/000000,000000,0000,00,9,99,'+job+',2,'+str(i)\
            +'.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=' \
             '99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=' \
             '-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='
        response=request.urlopen(url)
        html=response.read().decode('gbk') # 获取网页字符串 html
        return html
    
    
#编写正则,提取网页内容
def getdata(Jobname,StartNum,EndNum):
    allresult=[]
    for i in range(StartNum,EndNum):
        html=gethtml(Jobname,StartNum,EndNum) # 通过运行源码函数获取html
        # 编写正则用来提取信息,去掉的东西都用.*?来代替
        reg = re.compile('',re.S)
        result=re.findall(reg,html) # 获得一页的内容
        allresult+=result  # 通过循环,将获得的每一页内容添加到allresult中
    return allresult


#存储到excel
def savetoexcel(Jobname,StartNum,EndNum):
    data=getdata(Jobname,StartNum,EndNum) # 获取上面爬取的所有数据
    #判断文件是否存在
    if os.path.exists('51job职位信息.xlsx'):
        workbook=load_workbook('51job职位信息.xlsx')
        sheetnames = workbook.sheetnames # 获取51job职位信息.xlsx的所有sheet名
        #判断sheetname是否存在
        if Jobname in sheetnames:
            sheet=workbook[Jobname]
            values=list(sheet.values) # 获取sheet 的所有内容
            non_repeat=list(set(data).difference(set(values))) # 找出data与excel的不重复数据
            for each in non_repeat:
                sheet.append(each) # 将不重复数据写入
                #这里有个小BUG,如果数据里有一个值为空,例:'薪资'为空,则代码不断run出该条数据为不重复数据,会重复写入

        else:
            sheet=workbook.create_sheet(Jobname)
            sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
            for each in data:
                sheet.append(each)
    else:
        workbook=Workbook()
        sheet=workbook.active
        sheet.title=Jobname
        sheet.append('职位名,公司名,工作地点,薪资,发布时间'.split(','))
        for each in data:
            sheet.append(each)

    workbook.save('51job职位信息.xlsx')


#存储到mysql
def savetomysql(Jobname,StartNum,EndNum):
    connection = pymysql.connect(
        host='localhost',
        user='root',
        password='1234',
        db='jobinfo',
        charset='utf8'
    )
    cursor=connection.cursor()
    # 如果数据表不存在,则执行建表,这里表名用的是中文表名
    cursor.execute('create table if not exists '+Jobname+\
        '(id int(11) primary key auto_increment,' \
        'jobname varchar(100) not null,' \
        'company varchar(100) not null,' \
        'address varchar(50),' \
        'salary varchar(50),' \
        'ptime varchar(50))' \
        'default charset utf8;')
    cursor.execute('select jobname,company,address,salary,ptime from '+Jobname)
    connection.commit()
    all = cursor.fetchall()#获取数据表的数据
    length = len(all)#获取数据表的最后一个id
    count = 0
    data=getdata(Jobname,StartNum,EndNum)# 获取爬取的数据
    for each in data:
        if each not in all: # 确定要写入的数据不在数据表内
            count+=1
            sql='insert into '+Jobname+' values '+str((count+length,)+each)+';'
            cursor.execute(sql)
        connection.commit()

    cursor.close()
    connection.close()
#这里有个小bug,函数执行时,如果第一次执行和第二次执行,没有更改StartNum,则不会写入新数据


if __name__ == '__main__':
    savetoexcel('视频制作',1,3)
    savetomysql('运维',2,4)

 

你可能感兴趣的:(Python,编程语言,数据挖掘,爬虫,Python)