8.2 拉勾网爬虫实现
8.2.1 拉勾网爬虫的初步实现
下面按照上节的分析,编写拉勾网爬虫代码。
第一步,导入各种包。
import requests from lxml import etree import time import csv
第二步,编写保存函数。
def csv_write(item):
with open('lagou.csv', 'a', encoding='gbk', newline='') as csvfile:
writer = csv.writer(csvfile)
try:
writer.writerow(item)
except Exception as e:
print('write error!', e)这个保存函数与前几章编写的不同之处在于增加了 try 和 except,使这个函数能够捕捉并打印保存产生的错误。
第三步,编写最主要的爬虫函数 spider,其参数就是招聘职位列表页面 URL。
def spider(list_url):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) \
AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/62.0.3202.89 Safari/537.36'}
r = requests.get(list_url, headers=headers) #获取列表页
time.sleep(2)
res = r.json() #使用 json 解码
#循环处理招聘列表
for comp in res['content'] ['data']['page']['result']:
com_detail_url = 'http://m.lagou.com/jobs/'
+ str(comp['positionId']) + '.html'
#构造详情页 URL
response = requests.get(com_detail_url, headers=headers)
#获取详情页
time.sleep(2)
sel = etree.HTML(response.text)
try:
workyear = sel.xpath("//span[@class='item workyear']"
"/span/text()")[0].strip() #解析年限要求
except:
workyear = ''
try:
education = sel.xpath("//span[@class='item education']"
"/span/text()")[0].strip()#解析学历要求
except:
education =''
try:
content = sel.xpath("string(//div[@class='content'])")strip()
except:
content =''
city = comp['city'] #提取城市信息
company = comp['companyName'] #提取公司名称
createTime = comp['createTime'] #发布时间
position = comp['positionName'] #职位名称
salary = comp['salary'] #工资信息
item = [city, company, createTime, position, salary,
education, workyear, content]
csv_write(item) #使用 csv_write 函数保存
print('正在抓取:', company) 上面的代码比较长,下面一行一行地解释。
为了防止被拉勾网反爬虫禁止,这里首先定义了 headers 模拟真实浏览器。然后 GET 传入的 URL,这里同样为了防止被反爬虫禁止,等待两秒,然后使用 Requests 的 json 解码器解码得到的响应内容,解析出的内容是一个嵌套的字典,可以从中取出职位列表数据。对这个列表迭代,取出每一个职位的 positionId 并构造出这个职位的详情页 URL,然后继续请求详情页并解析出年限要求、学历及职责描述等数据。为了防止有的公司对某一项没有要求出现缺失值,进而引起保存函数错误,这里使用了 try 和 except 设置缺失值为空字符串。
然后继续从字典中提取出职位列表页面中其他感兴趣的数据,最后构造 list,使用保存函数保存到 csv 文件中。这就是上面爬虫函数 spider 完成的任务。
下面写主函数,主要就是构造列表页面 URL,并传进上面写好的 spider 函数里,然后执行爬取。
if __name__ == '__main__':
all_url =
['http://m.lagou.com/search.json?city=%E5%85%A8%E5%9B%BD \
&positionName=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&pageNo='
+ str(x)+'&pageSize=15'for x in range(1, 180)]
for url in all_url:
spider(url) 这里用列表推导式生成待爬取的 URL 列表,然后使用 for 循环,依次使用 spider 函数爬取。
8.2.2 拉勾网爬虫的进一步完善
上面已经按照思路写好了拉勾网爬虫代码,如果在 pycharm 中运行测试,很有可能会出现如图 8-9 所示的错误。

图 8-9 运行爬虫的错误提示
这是定义的保存函数 csv_write 提示的一个错误。write error! 'gbk' codec can't encode character '\xa0' in position 181: illegal multibyte sequence。
这个错误说明在保存数据到 csv 文件时,由于数据中包含\xa0 这个特殊符号,不能使用 gbk 编码而抛出一个错误。这个错误也说明在保存函数中增加捕捉错误的代码是非常有必要的。要解决这个问题,只需要将\xa0 替换为空字符串即可。我们可以很容易判断出这个符号是出现在 zhize 这个字段中的,在解析 zhize 这行代码的后面增加一个替换就好了。
content = sel.xpath(
"string(//div[@class='content'])").strip().replace('\xa0', '')这样再次运行这个爬虫程序,发现可以正常爬取网页了,但是查看爬取下来的 csv 文件,会发现只有前 5 行数据,以及后面断断续续的部分数据,有年限要求、学历要求和岗位职责这 3 个字段的信息,这是一个非常奇怪的问题。如果遇到这个问题,就要考虑是不是没能抓取到这些字段的职位详情页页面布局与能抓取到的不同?通过仔细地分析和比对,我们发现所有职位详情页页面布局完全相同,在命令行中对单个页面进行抓取解析,是能够获取到这 3 个字段的数据的。
这个问题是以前没有遇到过的,同样的页面布局,有的时候能抓取到数据,有的时候却不能,这时应该考虑,是不是触发了拉勾网的反爬虫机制?
很显然,仅仅有一小部分网页能被抓取成功,是触发了服务器的反爬虫策略。服务器检测到爬虫行为,会禁止一段时间,等过了这段时间后,爬虫又能爬取了,然后又被禁止,最后造成仅有小部分数据能被完整爬取。
既然可以确定是被反爬虫禁止,我们就需要思考,拉勾网是通过什么机制检测到爬虫的呢?下一节将讨论这个问题。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论