一. API
-
定义
API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。 目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问原码,或理解内部工作机制的细节。 -
使用方法
API用一套非常标准的规则生成数据,而且生成的数据也是按照非常标准的方式组织的。 因为规则很标准,所以一些简单,基本的规则容易学,可以迅速掌握API 的用法。但不是所有的API使用都简单。有些API的规则 很多,并且很复杂,因此在使用之前可以查看API的相关帮助文档信息 -
API的验证
1)有一些简单的是不需要验证操作的。是免费的API
2) 大部分的API 都是需要用户提交验证的。提交验证的目的主要是为了计算API调用的费用,这是常见的付费API 。eg:图灵的聊天机器人
二. 项目案例 —— 拉钩网数据采集
(一)需求分析
通过数据采集,得到拉钩网中发布的职业职位的需求分析
(二)数据解析及实验结果
- 首先分析网站的详情页面(此时关键字采用python)在真实的请求网址中,网页会给我们返回的是一个JSON串,需要解析这个JSON串就可以得到页面的信息。 通过改变Form Data 中的pn 的值来控制翻页
- 从页面的详情页中,我们要得到“ 职位名称 ”“ 职位描述”,” 任职要求 “等信息
1)首先我们请求头信息
我们需要构造的请求头Headers信息,这里如果没有构建好的话,容易被网站识别成爬虫,从而拒绝我们的请求
2) 表单信息
发送POST 请求时需要包含的表单信息(Form Data) , 需要解析出访问的页数码,还有搜索的关键字
3) 返回JSON数据
我们可以通过网页发现,我们所需要的信息在ocntent ——> positionResult——> result里面,其中包含了工作地点,职位信息,公司名称等。这些正是我们所需要的数据。
相关代码:
配置文件中:(该文件的作用是:之后的想要爬取别的类别,或者想要修改相关的参数的时候,直接在该文件中进行修改即可)
from fake_useragent import UserAgent
import requests
Host = 'www.lagou.com'
Origin = 'https://www.lagou.com'
Refer = 'https://www.lagou.com/jobs/list_python'
Connection = 'keep-alive'
Accept = 'application/json,text/javascript,*/*; q=0.01'
ua = UserAgent(verify_ssl=False)
ThreadCount = 50
csv_filename = 'filename.csv'
pages = 20
keyword = "python"
解析页面的核心代码:
#需要导入的模块
import time
import pandas as pd
import requests
from config import *
import logging
from concurrent.futures import ThreadPoolExecutor
import pprint
# 灵活配置日志级别,日志格式,输出位置
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='lagou.log',
filemode='w')
# 获取PositionID所在的页面,返回的是json数据
def getPositionIDPage(url_start, url_parse, page=1, kd='python'):
# 构造请求头(headers)
headers = {'User-Agent': ua.random,
'Host': Host,
'Origin': Origin,
'Referer': Refer,
'Connection': Connection,
'Accept': Accept,
'proxies': proxy}
# 构造表单
data = {
'first': False,
'pn': str(page),
'kd': kd
}
try:
# requests库里面的session对象能够帮助我们跨请求保持某些参数
# 也会在同一个session实例发出的所有请求之间保持cookies
# 创建一个session对象
session = requests.Session()
# 用session对象发出get 请求,设置cookies
session.get(url_start, headers=headers, timeout=3)
cookie = session.cookies
# 用session对象发出另一个请求post,获取cookies,返回响应信息
response = session.post(url=url_parse,
headers=headers,
data=data)
time.sleep(1)
# 响应状态码是4XX客户端错误,5XX 服务端响应错误,抛出异常
response.raise_for_status()
response.encoding = response.apparent_encoding
except Exception as e:
logging.error("页面" + url_parse + "爬取失败:", e)
else:
logging.info("页面" + url_parse + "爬取成功" + str(response.status_code))
return response.json()
运行测试:
if __name__ == '__main__':
url_start = 'https://www.lagou.com/jobs/list_%s' % (keyword)
url_parse = 'https://www.lagou.com/jobs/positionAjax.json?px=default&needAddtionalResult=false'
content = getPositionIDPage(url_start, url_parse, page=page, kd=keyword)
pprint(content)
实现的效果:
3. 爬取相关职位信息
获取所需的职位的标签 ,每一页招聘信息都会有一个所属的标签
positions = html['content']['positionResult']['result']
pprint.pprint(html)
df = pd.DataFrame(positions)
4. 存储信息
当我们可以将所需要爱的页面信息找到,并且爬取出来的时候,我们将爬取到的职位信息,存储到csv文件中
def save_as_csv():
#开启进程池
with ThreadPoolExecutor(ThreadCount) as pool:
#map方法: 可迭代对象传入函数是从前到后逐个提取元素,并且将结果依次保存在results中。
results = pool.map(task, range(1, pages + 1))
# total_df:拼接所有的信息,(axis=0,代表列拼接)
total_df = pd.concat(results, axis=0)
total_df.to_csv(csv_filename, sep=',', header=True, index=False)
logging.info("文件%s 存储成功" % (csv_filename))
return total_df
注: 这里所采用的是线程池的方式来进行解析和保存
实现的效果:
-
数据分析
成功爬取之后,我们可以对所拥有的数据进行分析,来看各个职位的统计信息import pandas as pd from config import * import matplotlib.pyplot as plt import matplotlib # 修改配置中文字字体和大小的修改 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['font.family'] = 'sans-serif' matplotlib.rcParams['font.size'] = 12 plt.rcParams['axes.unicode_minus'] = False df = pd.read_csv(csv_filename, encoding='utf-8') def show_seconfd_type(): # 获取职位类别分类,并分组统计 secondType_Series = df['secondType'].value_counts() print(secondType_Series) # 设置图形大小 plt.figure(figsize=(10, 5)) secondType_Series.plot.bar() plt.show() #实习和全职的统计 def show_job_nature(): jobNature_Series = df['jobNature'].value_counts() print(jobNature_Series) plt.figure(figsize=(10, 5)) jobNature_Series.plot.pie() plt.show() # 获取招聘公司 def show_company(): companyShortName_Series = df['companyShortName'].value_counts() companyShortName_Series_gt5 = companyShortName_Series[companyShortName_Series > 2] plt.figure(figsize=(10, 5)) companyShortName_Series_gt5.plot.bar() plt.show() if __name__ == '__main__': show_seconfd_type() show_job_nature() show_company()
实现的效果: