嗨~我是小鱼
最近暑假来临,好多小伙伴都在找暑期实习吧?前几天,一个朋友的弟弟,想在大三暑假期间找个实习工作锻炼自己,可是面对网络上几千条实习招聘信息,简直让人头大。随后朋友向我发出了“请求帮助”的信息,在了解大致情况后,立马用爬虫爬取了实习网的的信息,将数据结果发了过去,问题分分钟解决。这请我吃一顿饭不过分吧?
这篇爬虫实战教程,不仅适合新手练习爬虫,也适合需要找实习信息的朋友!
希望在看了这篇文章后,能够清晰的知道整个爬虫流程,并且能够独立自主的完成,其次,能够通过自己的爬虫实战,获取自己想要的信息。
好了,话不多说,咱们就开始吧!
内容主要分为两大部分:
首先,我们应该要知道自己的爬虫目标是个什么东西吧?俗话说,知己知彼,百战不殆。我们已经知道自己要爬取的页面是“实习网”,所以,咱们首先得去实习网看看,都有些什么数据。
实习网址:https://www.shixi.com/search/index
页面如下:
例如我们要找的岗位是“品牌运营”岗位的数据。因此直接在网页的搜索框输入品牌运营就行了。你会发现url发生了变化!
注意:我们要爬取的页面就是这页:https://www.shixi.com/search/index?key=品牌运营
在我们的爬取页面中,我们需要观察有哪些数据,并且一个页面中有几条数据。这个非常重要,关系到后面的代码编写,以及可以帮你检查,是否爬取到了页面的所有信息。
此时,我们要注意的是,我们所在的页面是“一级页面”,在浏览过程中,我们 点击随意一个岗位进入后呈现的是“二级页面”,此时你也会发现url又发生了变化。
例如,我们点一个品牌运营实习,二级页面就会自动跳转成这样,产生一个新的链接。如图:
我们在分析过程中发现,有些信息是在一级页面中,有些是在二级页面中。
在一级页面中,我们可以获取那些信息呢?如图所示:
总共有五条有效数据:职位、公司名、学历、薪资、地址
在二级页面中,我们来看看可以获取什么有效数据,领域和规模,阶段如果你觉得重要的话,也可以纳入爬虫范围,但是我个人认为,这并不影响实习,毕竟不是找正式工作,影响不会很大,反而是招聘实习生的数量更为重要,这里并未显示招聘人数,无法在图片上呈现,后续可加上。
到这里,我们一共需要抓取7个数据,加上“人数”一共8个数据,这也就是我们爬虫的最终目标数据。
这里分析下什么叫静态网页,什么叫动态网页。静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了--除非你修改页面代码。而动态网页则不然,页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。
它们的区别就在于:静态网页中的数据,是一劳永逸,也就是说一次性给你。动态网页中的数据,是随着页面一步步加载出来,而逐步呈现的,也就是你用静态网页的爬虫技术,无法获取到其中所有的数据。
值得强调的是,不要将动态网页和页面内容是否有动感混为一谈。这里说的动态网页,与网页上的各种动画、滚动字幕等视觉上的动态效果没有直接关系,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,只要是采用了动态网站技术生成的网页都可以称为动态网页。
点击 “鼠标右键”,点击 “查看网页源代码”,最终效果如图(部分截图):
这就是,最终反馈给你的数据,如果你发现自己想要的数据都在这里面,那么就可以说是静态页面,如若不然,则考虑为“动态页面”。
今天这里的案例是静态网页。
大家知道,在写代码之前要先知道,我们要用哪些方式,哪些库,哪些模块去帮你解析数据。常见用来解析数据的方法有:re正则表达式、xpath、beatifulsoup、pyquery等。
我们需要用到的是xpath解析法来分析定位数据。
爬虫的第一步是要考虑好,爬虫过程中需要用到哪些库,要知道python是一个依赖于众多库的语言,没有库的Python是不完整的。
import pandas as pd # 用于数据存储 import requests # 用于请求网页 import chardet # 用于修改编码 import re # 用于提取数据 from lxml import etree # 解析数据的库 import time # 可以粗糙模拟人为请求网页的速度 import warnings # 忽略代码运行时候的警告信息 warnings.filterwarnings("ignore")
url = 'https://www.shixi.com/search/index?key=品牌运营&districts=&education=0&full_opportunity=0&stage=0&practice_days=0&nature=0&trades=&lang=zh_cn' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'} rqg = requests.get(url, headers=headers, verify=False) ① rqg.encoding = chardet.detect(rqg.content)['encoding'] ② html = etree.HTML(rqg.text)
这里我们要注意①②两个地方。在①处,有两个参数,一个是headers一个是verify。其中headers是一种反反扒的措施,让浏览器认为爬虫不是爬虫,而是人在用浏览器去正常请求网页。verify是忽略安全证书提示,有的网页会被认为是一个不安全的网页,会提示你,这个参数你记住就行。
在②处,我们已经获取到了网页的源码。但是由于网页源代码的编码方式和你所在电脑的解析方式,有可能不一致,返回的结果会导致乱码。此时,你就需要修改编码方式,chardet库可以帮你自动检测网页源码的编码。(一个很好用的检测文档编码的三方库chardet)
# 1. 公司名 company_list = html.xpath('//div[@class="job-pannel-list"]//div[@class="job-pannel-one"]//a/text()') company_list = [company_list[i].strip() for i in range(len(company_list)) if i % 2 != 0] # 2. 岗位名 job_list = html.xpath('//div[@class="job-pannel-list"]//div[@class="job-pannel-one"]//a/text()') job_list = [job_list[i].strip() for i in range(len(job_list)) if i % 2 == 0] # 3. 地址 address_list = html.xpath('//div[@class="job-pannel-two"]//a/text()') # 4. 学历 degree_list = html.xpath('//div[@class="job-pannel-list"]//dd[@class="job-des"]/span/text()' # 5. 薪资 salary_list = html.xpath('//div[@class="job-pannel-two"]//div[@class="company-info-des"]/text()') salary_list = [i.strip() for i in salary_list] # 获取二级页面的链接 deep_url_list = html.xpath('//div[@class="job-pannel-list"]//dt/a/@href') x = "https://www.shixi.com" deep_url_list = [x + i for i in deep_url_list]
此时,你可以看到,我直接采用xpath一个个去解析一级页面中的数据分析。在代码末尾,可以看到:我们获取到了二级页面的链接,为我们后面爬取二级页面中的信息,做准备。
demand_list = [] area_list = [] scale_list = [] for deep_url in deep_url_list: rqg = requests.get(deep_url, headers=headers, verify=False) ① rqg.encoding = chardet.detect(rqg.content)['encoding'] ② html = etree.HTML(rqg.text) ③ # 6. 招聘人数 demand = html.xpath('//div[@class="container-fluid"]//div[@class="intros"]/span[2]/text()') # 7. 公司领域 area = html.xpath('//div[@class="container-fluid"]//div[@class="detail-intro-title"]//p[1]/span/text()') # 8. 公司规模 scale = html.xpath('//div[@class="container-fluid"]//div[@class="detail-intro-title"]//p[2]/span/text()') demand_list.append(demand) area_list.append(area) scale_list.append(scale)
要注意的是,二级页面也是页面,在爬取其中的数据时,也需要请求页面。所以,①②③处的代码,都是一模一样的。
https://www.shixi.com/search/index?key=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=1 https://www.shixi.com/search/index?key=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=2 https://www.shixi.com/search/index?key=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page=3
随意复制几个不同页面的url,观察它们的区别。这里可以看到,也就page参数后面的数字不同,是第几页,数字就是几。
x = "https://www.shixi.com/search/index?key=品牌运营&page=" url_list = [x + str(i) for i in range(1,61)]
由于我们爬取了60页 的数据,这里就构造出了60个url,他们都存在url_list这个列表中。
我们现在来看看整个代码吧,我就不再文字叙述了,直接在代码中写好了注释。
import pandas as pd import requests import chardet import re from lxml import etree import time import warnings warnings.filterwarnings("ignore") def get_CI(url): # 请求获取一级页面的源代码 url = 'https://www.shixi.com/search/index?key=品牌运营&districts=&education=0&full_opportunity=0&stage=0&practice_days=0&nature=0&trades=&lang=zh_cn' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'} rqg = requests.get(url, headers=headers, verify=False) rqg.encoding = chardet.detect(rqg.content)['encoding'] html = etree.HTML(rqg.text) # 获取一级页面中的信息:一共有5个信息。 # ①公司名 company_list = html.xpath('//div[@class="job-pannel-list"]//div[@class="job-pannel-one"]//a/text()') company_list = [company_list[i].strip() for i in range(len(company_list)) if i % 2 != 0] #②岗位名 job_list = html.xpath('//div[@class="job-pannel-list"]//div[@class="job-pannel-one"]//a/text()') job_list = [job_list[i].strip() for i in range(len(job_list)) if i % 2 == 0] #③地址 address_list = html.xpath('//div[@class="job-pannel-two"]//a/text()') # ④ 学历 degree_list = html.xpath('//div[@class="job-pannel-list"]//dd[@class="job-des"]/span/text()') # ⑤薪资 salary_list = html.xpath('//div[@class="job-pannel-two"]//div[@class="company-info-des"]/text()') salary_list = [i.strip() for i in salary_list] # ⑥获取二级页面的内容 deep_url_list = html.xpath('//div[@class="job-pannel-list"]//dt/a/@href') x = "https://www.shixi.com" deep_url_list = [x + i for i in deep_url_list] demand_list = [] area_list = [] scale_list = [] # 获取二级页面中的信息: for deep_url in deep_url_list: rqg = requests.get(deep_url, headers=headers, verify=False) rqg.encoding = chardet.detect(rqg.content)['encoding'] html = etree.HTML(rqg.text) #① 需要几人 demand = html.xpath('//div[@class="container-fluid"]//div[@class="intros"]/span[2]/text()') # ②公司领域 area = html.xpath('//div[@class="container-fluid"]//div[@class="detail-intro-title"]//p[1]/span/text()') # ③公司规模 scale = html.xpath('//div[@class="container-fluid"]//div[@class="detail-intro-title"]//p[2]/span/text()') demand_list.append(demand) area_list.append(area) scale_list.append(scale) # ④ 将每个页面获取到的所有数据,存储到DataFrame中。 data = pd.DataFrame({'公司名':company_list,'岗位名':job_list,'地址':address_list,"学历":degree_list, '薪资':salary_list,'岗位需求量':demand_list,'公司领域':area_list,'公司规模':scale_list}) return(data) x = "https://www.shixi.com/search/index?key=数据分析&page=" url_list = [x + str(i) for i in range(1,61)] res = pd.DataFrame(columns=['公司名','岗位名','地址',"学历",'薪资','岗位需求量','公司领域','公司规模']) # 这里进行“翻页”操作 for url in url_list: res0 = get_CI(url) res = pd.concat([res,res0]) time.sleep(3) # 保存数据 res.to_csv('aliang.csv',encoding='utf_8_sig')
这样一套下来,爬虫的思路是不是瞬间清晰明了?眼睛:我会了!手:我还是不会。得多加练习啊。初学者不要急于求成,项目不在多,在精。踏踏实实吃透一个远比看会十个更有效。
想要获取源代码的小火伴们,点赞+评论,私聊哦~
小鱼建立了一个新手交流群,可以为大家答疑解惑,想要获取源代码的也可以进群获取哦!里面还有100个练手项目+源代码~
交流群:954526228(注意进群暗号是:小鱼)
快来和小鱼一起成长进步吧!
① 2000多本Python电子书(主流和经典的书籍都有)
② Python标准库资料(最全中文版)
③ 项目源码(四五十个有趣且经典的练手项目及源码)
④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)
⑤ Python学习路线图(告别不入流的学习)