|
之前接触爬虫完全是没事干,看到有文章写,跟着自己做做,实际工作也不用,对于各种反爬、反反爬,都是一知半解,因为一直认为用不到,所以没必要研究
某天突然有个需求,说是搞一个爬虫的小应用,用于爬取51job的岗位,方便做一些策略,没办法,只有一个人,就只能自己重新看书搞了。
先加载需要的一些模块
import requests # 爬取库
from fake_useragent import UserAgent # UserAgent 库,它包含了大量的UserAgent可以随意进行替换
from datetime import datetime
import pandas as pd
import tkinter as tk # 交互UI模块
from PIL import ImageTk,Image
import time
import os
import logging # 日志模块
老规矩,直接上代码
"""
地区字典,便于根据不同城市爬取内容,后面的字段是51job中的每个地区的编码
"""
url_list = {
'深圳': '040000',
'武汉': '180200',
'成都': '090200',
'东莞': '030800'
}
"""
Page 作为用户手动输入的爬取量,测试的时候只给了100
"""
Page = 100
collections_items = []
# 主要的爬取函数
def get_index_list(keyword):
"""请求列表页数据"""
"""
设置请求头,一般都是把网页中的头直接复制过来,其中,需要说的是'User-Agent'直接采用UserAgent().random模块随机选择,这样也可以一定程度避免反爬
"""
headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Cookie':
'这里复制自己的就OK',
'Host': 'search.51job.com', # 列表页使用
'Referer':
'http://localhost:63342/Project/dutt_spider_project/ebay_spider/test.html?_ijt=2sl97mab32mnoetnb0d9usnsmo',
'Upgrade-Insecure-Requests': '1',
'User-Agent': UserAgent().random
}
data = []
page = 1
# 设置循环的条件
while page <= Page/50:
"""
个人认为,爬虫主要的两个问题是反爬机制和url的解读,反爬机制太宽泛了,以后再说。先说说url解读,F12直接可以看到单页的url,
但是当开始循环、传参时,每个url的区别就需要明确的知道,以便之后可以通过参数的方式传递,实现多页、多内容的爬取。这个过程
可能需要测试、观察好久。
以下面51job的url为例:
090200:是地区编码
第一个参数的位置:是搜索的关键词
第二个参数的位置:是页数的参数
另外,51job的返回内容是json格式,所以直接用requests.get(url=urls, headers=headers).json()整理了数据
之后就是字典的get()方法,获取对应键的值
最后把所有的数据转换成DataFrame,当然也可以直接加载到数据库中
"""
urls = 'https://search.51job.com/list/090200,000000,0000,00,9,99,{},2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare='.format(
keyword, page)
res = requests.get(url=urls, headers=headers).json()
items_list = res.get('engine_search_result')
if items_list:
vau = []
for i in items_list:
item = {}
item['keyword'] = keyword
item['job_name'] = i.get('job_name')
item['company_name'] = i.get('company_name')
item['workplace'] = i.get('workarea_text')
item['pay'] = i.get('providesalary_text')
item['release_time'] = i.get('updatedate')
item['link'] = i.get('job_href')
item['is_crawl'] = 1
item['get_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
item['company_nature'] = i.get('companytype_text')
item['company_scale'] = i.get('companysize_text')
item['work_experience'] = ''.join(
[s for s in i.get('attribute_text') if '经验' in s])
education_list = [
'初中', '高中', '大专', '本科', '硕士', '博士', '无学历要求', '初中及以下',
'高中/中技/中专'
]
item['education_required'] = ''.join([
s for s in i.get('attribute_text') if s in education_list
])
item['contact_address'] = i.get('workarea_text')
item['social_benefits'] = '/'.join(i.get('jobwelf_list'))
vau.append(item)
# collections_items.insert_many(vau)
page = page + 1
time.sleep(2)
result = pd.DataFrame(vau)
data.append(result)
else:
break
all_data = pd.concat(data)
return all_data
之后就是把整个爬取的函数放置在ui函数内部,实现最终的需求
就像下面这样 👇👇👇
跟新:5/28
因为还需要岗位信息,所以需要加一段代码,但是岗位信息要发生页面跳转才能看到,所以速度相对就下降了很多,所以也增加了选择下拉框,代码如下:
# 判断是否需要岗位信息
if select == "是":
# 需要说明的是这里的i还是之前的字典数据,"job_href"这个是跳转网址的键,
res1 = requests.get(url=str(i.get("job_href")), headers=headers)
# 网页返回出现乱码,所以解码格式换成中文的
res1.encoding = "gb2312"
# 这里使用了BeautifulSoup模块解析html文件
soup = BeautifulSoup(res1.text, 'lxml')
# 其实这里的提取很粗略,只是个大概,有什么好办法请大家多多指教
item['描述'] = soup.select('.bmsg>p')
else:
item['描述'] = ""
另外,增加下拉框的代码如下:
# 需要注意的是,下拉框是在tkinter的ttk下,所以必先 from tkinter import ttk,其他的放置和之前的一样
com = ttk.Combobox(app) # #创建下拉菜单
com.place(x=415, y=235, relwidth=0.28, relheight=0.06) # #将下拉菜单绑定到窗体
com["value"] = ("是", "否") # #给下拉菜单设定值
com.current(1) # #设定下拉菜单的默认值为第2个,即否
修改后,实现最终的需求就像下面这样 👇👇👇