《纽约时报》2012年2月的一篇专栏中所称,“大数据”时代已经降临,在商业、经济及其他领域中,决策将日益基于数据和分析而作出,而并非基于经验和直觉。随大数据时代一起来来临的,是越来越多的大数据工作岗位。在此,我们利用Python编程,抓取智联招聘、51job等网站上面有关大数据的工作岗位数据。

爬虫基础知识

数据来源

网络爬虫的数据一般都来自服务器的响应结果,通常有html和json数据等,这两种数据也是网络爬虫的主要数据来源。

其中html数据是网页的源代码,通过浏览器-查看源代码可以直接查看,例如:

简书主页部分源码示例

json是一种数据存储格式,往往包含了最原始的数据内容,一般不直接显示在网页中,这里我们可以通过Chrome浏览器-开发者工具中的Network选项捕获到服务器返回的json数据,例如:

简书首页json数据示例

数据请求

数据请求的方式一般有两种:GET方法和POST方法。我们也可以通过Chrome浏览器来捕获我们访问一个浏览器时的所有请求。这里以简书主页为例,打开Chrome浏览器开发者工具(F12),切换到Network选项,在地址栏输入http://www.jianshu.com/, 选择XHR类型,可以看到一条请求的内容,打开Headers,在General中可以看到请求方式为GET方式,

其中的Request Headers便是我们访问这个网页时的请求数据,如下图。

Request Headers

这个Headers可以用Python中的字典来表示,包含了用户请求的一些信息,例如编码、语言、用户登陆信息、浏览器信息等。

下面还有一个Query String Parameters,这里面包含了用户请求的一些参数,也是请求数据的一部分。

利用requests库请求数据

利用Python构建数据请求的方式有很多,在python3中,主要有urllib和requests两个类库可以实现该功能。urllib是官方标准库,其官方文档传送门。这里我们主要介绍第三方库requests,它是基于urllib编写的,比urllib用起来更加便捷,可以节约时间。

requests安装方法:

$ pip install requests

利用requests构建数据请求主要方式:

import requests

req = request.get(url)

或者

import requests

req = requests.post(url)

其中,get()与post()中都可以添加headers、params等参数,以字典的形式传递即可。一般来说,简单的网页通过传入url数据即可成功请求数据。不过一些网站采用了反爬虫机制,需要我们传入headers及params等参数,以模拟浏览器访问、用户登陆等行为,才可以正常请求数据。

利用webdriver请求数据

webdriver是一个用来进行复杂重复的web自动化测试的工具,能够使用chrome、firefox、IE浏览器进行web测试,可以模拟用户点击链接,填写表单,点击按钮等。因此,相对于requests库来说,webdriver在模拟浏览器鼠标点击滑动等事件上有着天然的优势,并且真实模拟了浏览器的操作,不易被反爬虫机制发现,因此是一个很好用的爬虫工具。当然,其缺点在于速度较慢,效率不高。

webdriver安装:

$ pip install selnium

除了安装selnium库,webdriver的运行还需要进行浏览器驱动的配置。Chrome、火狐和IE浏览器都有其配置方式,具体方法查看链接http://blog.163.com/yang_jianli/blog/static/1619900062014102833427464/。

这里我们以IE浏览器为例,做一个简单的示范:

from selenium import webdriver

import os

iedriver = "IEDriverServer.exe"

os.environ["webdriver.ie.driver"] = iedriver

driver = webdriver.Ie(iedriver)

如此,IE浏览器配置完毕,其中"IEDriverServer.exe"是IE浏览器驱动的存储路径。

于是,我们我们访问简书网主页数据只一步:

driver.get(http://www.jianshu.com/)

数据解析

使用requests请求下来的数据,可以利用.text()方法或者.content()方法访问,对于文本请求,二者并无太大差别,主要在于编码问题。具体用法可以参考官方文档,这里不再赘述。使用webdriver请求下来的数据可以用.page_source属性获取。请求下来的数据一般包含了大量的网页源代码,如何将其解析以提取出我们想要的内容呢?

html类型数据解析

html语言即超文本标记语言,它是由一个个html标签构成的,是结构化的语言,因此很容易从中匹配提取信息。这种类型的数据解析的方法有很多,比如利用正则表达式,按照html标签的结构进行字符串匹配,或则利用lxml库中的xpath方法使用xpath路径定位到每一个节点、也有类似jQuery的PyQuery方法。这里我们主要介绍BeautifulSoup方法。

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间。该介绍来源于其官方中文文档,传送门。利用BeautifulSoup我们能够将html字符串转化为树状结构,并非常快速地定位到每一个标签。

目前版本是BeautifulSoup4,pip安装方法:

$ pip install BeautifulSoup4

或者,下载bs4的源码,然后解压并运行:

$ python setup.py install

利用BeautifulSoup解析html数据的关键步骤为:

from bs4 import BeautifulSoup

soup = BeautifulSoup(req.contents, "html.parser")

如果采用webdriver请求数据,那么则是:

from bs4 import BeautifulSoup

soup = BeautifulSoup(driver.page_source, "html.parser")

如此,便将html数据转换成BeautifulSoup中的树状结构。然后利用BeautifulSoup中的find()、find_all()等方法即可定位到每一个节点。详情请参阅官方文档。

json类型数据解析

json类型的数据已经是高度结构化的数据,跟Python中字典的表示形式一样,因此在解析上十分方便。我们可以通过:

import json

data = json.loads(req.text)

直接读取json数据,且能够返回字典类型。

大数据职位数据爬虫实战

这里我们以51job网站为例,构建大数据相关职位的数据爬虫。其中搜索关键词为:

数据科学家

数据分析师

数据架构师

数据工程师

统计学家

数据库管理员

业务数据分析师

数据产品经理

网页分析

打开51job首页http://www.51job.com/, 在搜索框中输入“数据科学家”,将搜索框中的地区点开,去掉当前勾选的城市,即默认在全国范围搜索。点击“搜索”按钮,得到搜索结果。这时我们将网址栏URL复制出来:

http://search.51job.com/list/000000,000000,0000,00,9,99,

%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6,

2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99&degreefrom=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=

结果不止一页,点击第二页,同样将URL复制出来:

http://search.51job.com/list/000000,000000,0000,00,9,99,

%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6,

2,2.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99

&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0

&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=

很容易发现,这两段url唯一的不同在于".html"前面的数字1和2,因此它代表了页码。其中:

%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6

是一种URL编码,翻译成中文就是“数据科学家”,转换方式可以使用urllib库中的quote()方法:

import urllib.quote

keyword = '数据科学家'

url = quote(keyword)

我们可以通过第一次的搜索结果获取页码数:

def GetPages(keyword):

keyword = quote(keyword, safe='/:?=')

url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \

'&keywordtype=2&curr_page=1&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&fromType=14&dibiaoid=0&confirmdate=9'

html = requests.get(url)

soup = BeautifulSoup(html.content, "html.parser")

span = soup.find('div', class_='p_in').find('span', class_='td')

page_num = span.get_text().replace('共', '').replace('页,到第', '')

return page_num

由此,便可实现针对特定关键词的所有搜索结果的页面的遍历。

URL列表构建

打开搜索结果页面,我们会发现,点击职位名称可以链接到每个职位的详情页面,也正是我们所需要的数据源。因此,我们只需要获取所有的搜索结果中的职位名称的超链接地址,便可以遍历所有职位的详细数据:

def GetUrls(keyword, page_num):

keyword = quote(keyword, safe='/:?=')

urls = []

p = page_num+1

for i in range(1, p):

url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \

'&keywordtype=2&curr_page=' + \

str(i) + \

'&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&dibiaoid=0&confirmdate=9'

html = requests.get(url)

soup = BeautifulSoup(html.content, "html.parser")

ps = soup.find_all('p', class_='t1')

for p in ps:

a = p.find('a')

urls.append(str(a['href']))

s = random.randint(5, 30)

print(str(i)+'page done,'+str(s)+'s later')

time.sleep(s)

return urls

数据请求构建

在获取了所有的职位数据的url之后,我们使用requests访问这些url发现,并不能顺利获取数据。因此,可以考虑在请求中加入headers数据,其中包含cookie和User_Agent:

User_Agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'

cookie = 'guid=14842945278988500031; slife=indexguide%3D1'

headers = {'User-Agent': User_Agent, 'cookie': cookie}

这样,可以成功请求每个职位的详情页面数据:

数据解析

数据解析首先是明确数据需求,这里我们将数据尽可能多的抓取下来。

以职位要求一栏为例,我们通过访问多个页面对比发现,这一栏可能显示的要求个数不一样:

这里包括了经验、学历、招聘人数和发布时间

而这里则没有对于经验的要求。

利用浏览器开发者选项功能,查看这一栏的源码:

这里职位的要求都放在一个class="sp4"的span中,通过查找功能可以发现没有其他的class="sp4"的标签,所以我们利用find_all()方法可以轻松定位到这些职位要求数据。

通过比较可以发现这最多的要求个数为4,所以在个数不确定的情况下,可以先新建一个包含四个空字符串元素的新数组,将所有的要求个数填入该数组,这样可以保证不同网页的数据都能获取完整。

spans = soup.find_all('span', class_='sp4')

num = len(spans)

nav = ['', '', '', '']

for i in range(0, num-1):

nav[i] = spans[i].get_text().strip()

完整代码如下:

# -*- coding: utf-8 -*-

from urllib.parse import quote

import requests

from bs4 import BeautifulSoup

import time

import random

def GetPages(keyword):

keyword = quote(keyword, safe='/:?=')

url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \

'&keywordtype=2&curr_page=1&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&fromType=14&dibiaoid=0&confirmdate=9'

html = requests.get(url)

soup = BeautifulSoup(html.content, "html.parser")

span = soup.find('div', class_='p_in').find('span', class_='td')

page_num = span.get_text().replace('共', '').replace('页,到第', '')

return page_num

def GetUrls(keyword, page_num):

keyword = quote(keyword, safe='/:?=')

urls = []

p = page_num+1

for i in range(1, p):

url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \

'&keywordtype=2&curr_page=' + \

str(i) + \

'&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&dibiaoid=0&confirmdate=9'

html = requests.get(url)

soup = BeautifulSoup(html.content, "html.parser")

ps = soup.find_all('p', class_='t1')

for p in ps:

a = p.find('a')

urls.append(str(a['href']))

s = random.randint(5, 30)

print(str(i)+'page done,'+str(s)+'s later')

time.sleep(s)

return urls

def GetContent(url, headers):

html = requests.get(url, headers=headers)

soup = BeautifulSoup(html.content, "html.parser")

PositionTitle = str(soup.find('h1')['title'])

Location = soup.find('span', class_='lname').string

Salary = soup.find('strong').string

CompanyName = soup.find('p', class_='cname').get_text().strip()

CompanyType = soup.find(

'p', class_='msg ltype').get_text().strip().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '')

spans = soup.find_all('span', class_='sp4')

num = len(spans)

nav = ['', '', '', '']

for i in range(0, num-1):

nav[i] = spans[i].get_text().strip()

Exp = nav[0]

Degree = nav[1]

RecruitNum = nav[2]

PostTime = nav[3]

Welfare = soup.find('p', class_='t2')

if str(type(Welfare)) == "":

Welfare = ''

else:

Welfare = Welfare.get_text().strip().replace('\n', '|')

PositionInfo = soup.find(

'div', class_='bmsg job_msg inbox').get_text().strip().replace('\n', '').replace('分享', '').replace('举报', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace('\r', '')

PositionType = soup.find('span', class_='el')

if str(type(PositionType)) == "":

PositionType = ''

else:

PositionType = PositionType.get_text().strip().replace('\n', '')

Contact = soup.find('div', class_='bmsg inbox')

if str(type(Contact)) == "":

Contact = ''

else:

Contact = Contact.get_text().strip().replace(

' ', '').replace(' ', '').replace('地图', '').replace('\n', '')

ConpanyInfo = soup.find('div', class_='tmsg inbox')

if str(type(ConpanyInfo)) == "":

ConpanyInfo = ''

else:

ConpanyInfo = ConpanyInfo.get_text().strip().replace(

'\n', '').replace(' ', '').replace(' ', '')

try:

record = PositionTitle+'\t'+Location+'\t'+Salary+'\t'+CompanyName+'\t'+CompanyType+'\t'+Exp+'\t'+Degree+'\t' + \

RecruitNum+'\t'+PostTime+'\t'+Welfare+'\t'+PositionInfo + \

'\t'+str(PositionType)+'\t'+str(Contact)+'\t'+str(ConpanyInfo)

except Exception as e:

record = ''

else:

pass

finally:

pass

return record

def main():

with open('keywords.txt', 'r', encoding='utf-8') as f:

keywords = f.readlines()

for keyword in keywords[1:]:

keyword = keyword.strip()

page_num = int(GetPages(keyword))

urls = GetUrls(keyword, page_num)

with open(keyword+'urls.txt', 'w', encoding='utf-8') as f:

for url in urls:

f.write(url+'\n')

User_Agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'

cookie = 'guid=14842945278988500031; slife=indexguide%3D1'

headers = {'User-Agent': User_Agent, 'cookie': cookie}

with open(keyword+'urls.txt', 'r', encoding='utf-8') as f:

urls = f.readlines()

records = []

i = 0

for url in urls:

url = url.strip()

if url != '':

records.append(

GetContent(url, headers))

i += 1

s = random.randint(5, 30)

print(str(i)+'page done,'+str(s)+'s later')

time.sleep(s)

with open(keyword+'.txt', 'w', encoding='utf-8') as f:

for re in records:

f.write(re+'\n')

print(keyword+' Done---------------------------')

if __name__ == '__main__':

main()

python爬取网站大数据_[Python]爬虫抓取大数据职位数据相关推荐

  1. python爬虫实现股票数据存储_Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储!...

    Python爬虫可以说是好玩又好用了.现想利用Python爬取网页股票数据保存到本地csv数据文件中,同时想把股票数据保存到MySQL数据库中.需求有了,剩下的就是实现了. 在开始之前,保证已经安装好 ...

  2. python爬虫抓取动态网页数据_python网络爬虫抓取ajax动态网页数据:以抓取KFC门店地址为例...

    一,尝试用BeautifulSoup抓取 先打开KFC网站门店列表页面:http://www.kfc.com.cn/kfccda/storelist/index.aspx 可以看到门店列表如下图: 打 ...

  3. java爬虫抓取网页数据论坛_Java爬虫抓取网页

    Java爬虫抓取网页原作者:hebedich  原文链接 下面直接贴代码: import java.io.BufferedReader; import java.io.InputStreamReade ...

  4. python如何爬取网站所有目录_[python] 爬取网站所有的URL

    运行python脚本,最终程序目录下会是这样: result.txt中保存所有的URL 文件夹sh.neusoft.com中保存爬虫得到的所有网页 main.py的源代码如下 # -*- coding ...

  5. python爬取图片失败显示404_python3.7中Web抓取时出现http404错误

    我收到404错误代码(如下所示)当尝试对某个网站进行网页抓取时.在 我试着在不同的论坛上寻找答案,但找不到解决办法 有人有解决方案来修复这个404错误吗?>>> from urlli ...

  6. python获取app信息的库_基于python3抓取pinpoint应用信息入库

    这篇文章主要介绍了基于python3抓取pinpoint应用信息入库,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Pinpoint是用Java编写 ...

  7. python获取渲染之后的网页_使用Pyppeteer抓取渲染网页

    Pyppeteer是Puppeteer的非官方Python支持,Puppeteer是一个无头JavaScript的基于Chrome/Chromium浏览器自动化库,可以用于对渲染网页的抓取. 比较了P ...

  8. java 省市县数据_使用Jsoup抓取全国地区数据(省市县镇村)

    最近手头在做一些东西,需要一个全国各地的地域数据,从省市区到县镇乡街道的.各种度娘,各种谷歌,都没找到一个完整的数据.最后功夫不负有心人,总算找到一份相对来说比较完整的数据,但是这里的数据也只是精确到 ...

  9. java抓取页面数据_通过java抓取任何指定网页的数据

    假设你需要获取51job人才网上java人才的需求数量,首先你需要分析51job网站的搜索这一块是怎么运作的,通过解析网页的源代码,我们发现了以下一些信息: 1. 搜索时页面请求的URL是 http: ...

  10. wireshark 抓 蓝牙数据_使用Wireshark 抓取数据包

    Wireshark 是一个网络封包分析软件.网络封包分析软件的功能是获取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换. 一  ...

最新文章

  1. Google设想将《黑镜》情节变为现实,但要你的隐私作交换
  2. 函数式编程语言python-10分钟学会python函数式编程
  3. Selenium Webdriver——操作隐藏的元素(三)switchTo().frame()
  4. java io 文件是否存在,代码实例Java IO判断目录和文件是否存在
  5. SNMP、MIB、OID概念的理解
  6. 【计网】计算机网络期末总复习-谢希仁(个人总结)理论概念
  7. 文件上传linux服务器,Linux 文件上传Linux服务器
  8. 利用python画混淆矩阵
  9. Latex指南(part2)--Latex入门之组织文档结构
  10. 使用WebDeployment Project改善VS2005发布网站问题
  11. 现在的年轻人,正在努力的改变着一些东西
  12. oracle库锁表处理,oracle 数据库锁表处理 ORA-00031
  13. pythonios脚本语言-iOS开发Swift篇—(一)简单介绍
  14. Webstorm—Webstorm汉化(图文详解)
  15. 计算机十大经典算法整理
  16. 计算机术语翻译(Term.)及缩写整理(Abbr.)
  17. 计算机考研360能去哪里,计算机专业考研,有什么好的211院校推荐?
  18. 绿色版软件怎么添加鼠标右键菜单里
  19. 父进程退出,保证子进程交由init。
  20. Qt编写自定义控件:唱片播放控件

热门文章

  1. V4L2视频采集与H264编码4—X264编码H264视频
  2. 你不得不知道的通信行业基础介绍
  3. 网络通信基础(局域网、广域网、IP地址、端口号、协议、封装、分用)
  4. eoLinker-API_Shop_知识类API调用的代码示例合集:驾考题库、ISBN书号查询等
  5. 从零开始学习Android开发
  6. WindowsXP自带小工具(转)
  7. NumberFormat的使用
  8. 微博android4.1.2,微博客户端Fuubo
  9. A站、B站、C站、D站、E站、F站、G站、H站、I站、J站、K站、L站、M站、N站、O站、P站、Q站、R站、S站、T站、U站、V站、W站、X站、Y站、Z站都是什么网站?Q站是什么?
  10. Linux Vi 文本编辑器常用命令