最近想学点东西,又不知道学什么技术才有用,于是就有了一个想法,我把各大招聘网的任职要求都爬下来,然后做数据分析,看看哪些技术出现的频率多,最后我们把数据做成词云图展示出来,自然就知道最近比较火的技术是哪些了!
实现这个功能要用到的技术:
Scrapy请求网站爬取数据(当然你也可以不用Scrapy,通用爬虫一样能实现,只不过会麻烦一些)
Xpath解析网页(当然你也可以用其他方法解析)
cvs把数据保存到excel里面(还可以用pandas把excel数据直接导入数据库中)
jieba解析数据,分词解析、提取关键字
WordCloud制作词云图
下面我们就直接开始爬取了
今天爬取的是前程无忧的java职位要求,如需要爬取Python的自己修改参数一下参数就好
前程无忧官网:https://www.51job.com/
我们先进入官网查看,可以看到总共有7万多条数据,这就是我们最后需要爬取的总数据
我们先分析网站,我们需要拿到的是它每一个职位的任职要求,而这个信息我们是不能直接在网页上拿到的,我们需要点击某一个职位才能看到它的任职要求,然后我们点击一个查看一下,这就是我们需要的数据了
爬取思路:
由于我们的任职要求是无法直接在首页爬取到的,而是需要点击跳转才能获取到的,所以我们第一次请求时不获取数据,而是获取跳转链接,获取链接之后再把这个链接当成请求连接,解析我们需要的数据,然后把这一页的链接获取完之后,再获取翻页的跳转链接,爬取下一页的全部链接,最后我们通过判断翻页标签的状态来判断我们是否爬取完了整个网站的数据
思路讲清楚了,然后我们回过来用F12的元素选择器看看我们职位信息的详细情况,找到了我们的跳转连接,这样我们就能通过Xpath来爬取它的地址了
Xpath不会的也可以去看我的博客
然后我们再解析我们的任职要求,一样的通过F12元素选择器找所在标签的id或者class,我们就能通过Xpath解析到的所有内容
既然已经知道爬取数据源在哪了,也知道怎么爬取了,那么就开始上代码啦
我们先创建好一个scrapy项目,不知道怎么创建可以去看我上篇关于Scrapy入门的博客
https://blog.csdn.net/qq_43517653/article/details/103132714
主要爬虫代码
# -*- coding: utf-8 -*-
import scrapy
from ScraptySpider.items import ScraptyspiderItem
class Job51Spider(scrapy.Spider):
name = 'job51'
# 应为我们重复调用了请求,所以最好不标注爬取网站,中途可能会出问题
# allowed_domains = ['search.51job.com']
start_urls = ['https://search.51job.com/list/000000,000000,0000,00,9,99,Java,2,1.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=']
def parse(self, response):
msgs = response.xpath('//div[@id="resultList"]/div[@class="el"]')
for msg in msgs:
# 获取a标签的href
href= msg.xpath('./p/span/a/@href').extract_first()
yield scrapy.Request(url=href, callback=self.other_parse)
# 获取下一页标签
nextUrl = response.xpath('//div[contains(@class,"p_in")]/ul/li[last()]/a/@href').extract_first()
# 判断是否还有下一页
if nextUrl != None:
yield scrapy.Request(url=nextUrl, callback=self.parse)
def other_parse(self,response):
item = ScraptyspiderItem()
# 公司
company = response.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[1]/a/text()').extract_first()
# 地址
addr = response.xpath('/html/body/div[3]/div[2]/div[3]/div[2]/div/p/text()').extract_first()
# 职位介绍
skill = str(response.xpath('//div[contains(@class,"bmsg job_msg")]/p/text()').extract()).strip("[']")
if company != None and addr != None and skill != None:
# 调用管道存储数据
item['company'] = company
item['addr'] = addr
item['skill'] = skill
yield item
print(company)
print(addr)
print(skill)
我们保存数据的管道pipelines.py,把我们的数据存进cvs文件
import csv
class ScraptyspiderPipeline(object):
def __init__(self):
self.f = open("java51job.csv", "w", newline="")
# 保存文件
self.writer = csv.writer(self.f)
self.writer.writerow(["company", "addr", "skill"])
def process_item(self, item, spider):
# 52jobjava
company = item["company"]
addr = item["addr"]
skill = item["skill"]
self.writer.writerow([company,addr,skill])
return item
然后我们可以利用pandas模块直接把excel数据直接导入mysql之中
import pandas as pd
import pymysql
import csv
import codecs
conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='123', db='python', charset='utf8')
cursor = conn.cursor()
# 自动确认commit True
conn.autocommit(1)
# path = 'E:\PyCharmSpace\\pythonspider\ScraptySpider\ScraptySpider\xs.csv'
df = pd.read_csv('51job.csv', encoding='gbk')
print(df)
# 一个根据pandas自动识别type来设定table的type
def make_table_sql(df):
df2 = df.astype(object).where(pd.notnull(df), None)
columns = df2.columns.tolist()
types = df2.ftypes
print("--------------------------------------")
print(types)
# 添加id 制动递增主键模式
make_table = []
for item in columns:
if 'int' in types[item]:
char = item + ' INT'
elif 'float' in types[item]:
char = item + ' FLOAT'
elif 'object' in types[item]:
char = item + ' VARCHAR(255)'
elif 'datetime' in types[item]:
char = item + ' DATETIME'
make_table.append(char)
return ','.join(make_table)
# csv 格式输入 mysql 中
def csv2mysql(table_name, df):
# 创建table
cursor.execute('DROP TABLE IF EXISTS {}'.format(table_name))
cursor.execute('CREATE TABLE {}({})'.format(table_name,make_table_sql(df)))
# 提取数据转list 这里有与pandas时间模式无法写入因此换成str 此时mysql上格式已经设置完成
# df['日期'] = df['日期'].astype('str')
values = df.values.tolist()
print("------------------")
# for
# 根据columns个数
s = ','.join(['%s' for _ in range(len(df.columns))])
# executemany批量操作 插入数据 批量操作比逐个操作速度快很多
cursor.executemany('INSERT INTO {} VALUES ({})'.format(table_name,s), values)
if __name__ == "__main__":
csv2mysql('xs',df)
但是我们看这些数据还是明显有问题的,不仅有重复数据,因为样式的改变导致有空白数据,所以我们还要对数据进行处理,判空、去重复。
而且我们爬取的数据也太慢了,后期我们也会对爬取速度进行优化,利用多线程、多进程的爬虫来优化爬取速度
end…