你好,我是悦创。
我们前面入手的第一篇是糗事百科,这里就不细讲了,部分代码提供如下:
为爬取的笑话加序号:两种方法:
方法一:
方法二更加优雅和更加Python:
扩展:
筛选非空内容:
好,咱们进入正题!
一: 简单的请求(实习僧)
import requests
from bs4 import BeautifulSoup
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.shixiseng.com/'
# https://www.shixiseng.com/interns/?page=1&keyword=Python&city=%E5%8C%97%E4%BA%AC
for page in range(1,3):
req = requests.get(url + f'interns/?page={page}&keyword=Python&city=%E5%8C%97%E4%BA%AC', headers = header)
soup = BeautifulSoup(req.text, 'lxml')
print(soup.prettify())
一:抓取职位信息
- 分析(实习僧)
① 自己定义了一个字体:MyFont;
② 然后,通过编码格式、前端的js交互来展示到页面上;
③ 不因约定俗成的字体编码方式;
④ div.intern-wrap 选取形式
offers = soup.select('div.intern-wrap') # 得到的数据是list
⑤ 选取职位名称:
title = offer.select('a.title')[0].text
⑥ 选取薪资:
salary = offer.select('div.f-l p span.day')[0].text
截至目前的完整代码
import requests
from bs4 import BeautifulSoup
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.shixiseng.com/'
# https://www.shixiseng.com/interns/?page=1&keyword=Python&city=%E5%8C%97%E4%BA%AC
for page in range(1,2):
req = requests.get(url + f'interns/?page={page}&keyword=Python&city=%E5%8C%97%E4%BA%AC', headers = header)
soup = BeautifulSoup(req.text, 'lxml')
# print(soup.prettify())
offers = soup.select('div.intern-wrap') # 得到的数据是list
# print(offers)
for index, offer in enumerate(offers):
# 爬取单独的一个职位信息,自动解决全部
title = offer.select('a.title')[0].text
salary = offer.select('div.f-l p span.day')[0].text
print(f'{index}title:>{title}, salary:>{salary}')
运行结果:
空白(不能说空白吧,有爬取到,只不过在上面的控制台里面我们可以理解为空白)部分就是实习僧的反爬虫机制;接下来就来破解它!
二: 获取编码方式
-
字体有3000多个,我们分析运行结果可知,实习僧网站就设置了一些常用字体的编码方式,这样我们计算机并没有这些字体编码方式;而相对比之下:我们发现对应的薪资是一个都没有显示出来,毕竟薪资也就才由几个基本数字组合而成的:0、1、2、3、4、5、6、7、8、9
-
接下来关键词函数:encode()
-
在enconde()里面添加utf-8
-
encode('utf-8')
代码示例:
print(salary.encode('utf-8'))输出结果:
我们用encode的目的就是把salary获得到的数据解码成16进制,分析其中规律。
转换成16进制的utf-8的形式
分析该获得的16进制:
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xee\x84\x97\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\xbd\xa6\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\x98\x9a\xee\x98\x9a-\xee\xbb\xa0\xee\xb3\xaf\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\xbd\xa6\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\x84\x97\xee\x98\x9a\xee\x98\x9a-\xef\x9b\xa0\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xef\x9b\xa0\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\x84\x97\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\xbd\xa6\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\x98\x9a\xee\x98\x9a-\xee\xb3\xaf\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
b'\xee\xbb\xa0\xee\xbd\xa6\xee\x98\x9a-\xee\x84\x97\xee\x98\x9a\xee\x98\x9a/\xe5\xa4\xa9'
分析我们会发现:150是三个数字,而获取到的16进制有9个,那9÷3 = 3,我们就可以得到每三个组成一个数字;
那就可以得出:(这里得到的数据,并不能直接使用,因为实习僧使用的动态加密的。一段时间,这些得到的数据都会改变。
· 数字0对应 ---> \xee\x98\x9a
· 数字1对应 ---> \xee\xbb\xa0
· 数字2对应 ---> \xee\xb3\xaf
· 数字3对应 ---> \xee\x84\x97
· 数字4对应 ---> \xef\x9b\xa0
· 数字5对应 ---> \xee\xbd\xa6
· 数字6对应 ---> 略
· 数字7对应 ---> 略
· 数字8对应 ---> 略
· 数字9对应 ---> 略
普及:
\x >>>16进制
0、1>>>2进制
# ============================
# -*8 coding: utf-8 -*-
# @Author: 黄家宝
# @Corporation: AI悦创
# @Version: 1.0
# @Function: 简单爬取
# @DateTime: 2019-07-24 18:49:36
# ============================
import requests
from bs4 import BeautifulSoup
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.shixiseng.com/'
# https://www.shixiseng.com/interns/?page=1&keyword=Python&city=%E5%8C%97%E4%BA%AC
for page in range(1,3):
req = requests.get(url + f'interns/?page={page}&keyword=Python&city=%E5%8C%97%E4%BA%AC', headers = header)
soup = BeautifulSoup(req.text, 'lxml')
# print(soup.prettify())
offers = soup.select('div.intern-wrap') # 得到的数据是list
# print(offers)
for index, offer in enumerate(offers):
# 爬取单独的一个职位信息,自动解决全部
title = offer.select('a.title')[0].text
salary = offer.select('div.f-l p span.day')[0].text.encode('utf-8')
# print(f'{index}title:>{title}, salary:>{salary}')
salary = salary.replace(b'\xee\x98\x9a', b'0')
salary = salary.replace(b'\xee\xbb\xa0', b'1')
salary = salary.replace(b'\xee\xbb\xa0', b'2')
salary = salary.replace(b'\xee\x84\x97', b'3')
salary = salary.replace(b'\xef\x9b\xa0', b'4')
salary = salary.replace(b' \xee\xbd\xa6', b'5')
a = salary.decode('utf-8')
print(f'{index}title:>{title}, salary:>{a}')
注意:
· 我们在用encode编码之后还要用decode解码回去,而且如果encode里面用的是:utf-8,那decode里面也要用utf-8,同理:用的是gbk,我们decode也用gbk
· utf-8还可以这样写:utf8、utf_?
· 获取文字(文本):
- text()
- string()
- strings()
- stripped_strings()
- strip()
·replace()作用对象>>>字符串,是新建一个,而不是在本身创建;
代码示例:
# 注意观察
l = [1, 2, 3]
for i in l:
i = str(i)
i.replace('1', '100')
print(i)
# 注意对比
l = [1, 2, 3]
for i in l:
i = str(i)
a = i.replace('1', '100')
print(a)
扩展:爬取每个职位信息的详情(小小的深度爬取)
Ps:有问题公众号后台直接留言哦!skrskrskr~
或者去我的知识星球:
图例 :
分析:
对应代码:
import requests
from bs4 import BeautifulSoup
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.shixiseng.com/'
for index, page in enumerate(range(1,2)):
req = requests.get(url + f'interns/?page={page}&keyword=Python&city=%E5%8C%97%E4%BA%AC', headers = header)
soup = BeautifulSoup(req.text, 'lxml')
offers = soup.select('.f-l.intern-detail__job a')
print(offers)
输出结果观察
所以用get的方法获取:
for item in offers:
print(item.get('href'))
输出结果:
而且基本操作类似 >>> 那我们就可以把这个过程或者说请求写成一个函数detail_page:
首先,分析新页面:
切换另一个详情页看看:
所以,可想而知:
一言不合就扔代码:
def detail_page(new_url):
req = requests.get(new_url, headers = header)
soup = BeautifulSoup(req.text, 'lxml')
job_name = soup.select('.new_job_name')
print(job_name)
下一步就是:只要标题!!!
分析:上面结果可以看见,数据类型是一个个列表,然后需要获取文字:
有好多方法这里咱们来写一下:
def detail_page(new_url):
req = requests.get(new_url, headers = header)
soup = BeautifulSoup(req.text, 'lxml')
job_name = soup.select('.new_job_name')[0].text
print(job_name)
输出结果:
截至目前的完整代码:
# ============================
# -*8 coding: utf-8 -*-
# @Author: 黄家宝
# @Corporation: AI悦创
# @Version: 1.0
# @Function: 功能
# @DateTime: 2019-07-24 18:49:36
# ============================
import requests
from bs4 import BeautifulSoup
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.shixiseng.com/'
def detail_page(new_url):
req = requests.get(new_url, headers = header)
soup = BeautifulSoup(req.text, 'lxml')
job_name = soup.select('.new_job_name')[0].text
print(job_name)
for index, page in enumerate(range(1,2)):
req = requests.get(url + f'interns/?page={page}&keyword=Python&city=%E5%8C%97%E4%BA%AC', headers = header)
soup = BeautifulSoup(req.text, 'lxml')
offers = soup.select('.f-l.intern-detail__job a')
# print(offers)
for index, item in enumerate(offers):
print(item)
new_url = item.get('href') # 这个获取到的就是字符串,不信可以用内置函数type检测一下下
detail_page(new_url)
那其他的都一样了,就不一一来写和分析咯! 我公众号原文: 公众号原文 我是AI悦创,依然不会定时给你们分享一些有趣好玩实用的东西,欢迎关注~
警察蜀黍!就是这个人!脑子简直有泡!还不赶紧关注一下!