Python爬虫入门--official

爬虫入门之牛客网官方实习网页练习~~~~

urllib库

urllib提供的功能就是利用程序去执行各种HTTP请求。如果要模拟浏览器完成特定功能,需要把请求伪装成浏览器。伪装的方法是先监控浏览器发出的请求,再根据浏览器的请求头来伪装,User-Agent头就是用来标识浏览器的。

urllib是Python标准库的一部分,包含urllib.request,urllib.error,urllib.parse,urllib.robotparser四个子模块,这里主要介绍urllib.request的一些简单用法。

urllib.request

urllib.request.urlopen

urlopen()方法可以实现最基本请求的发起
urlopen(url,data,timeout)
url即为URL;
data是访问URL时要传送的数据;
timeout时设置超时时间;
第二、三参数是可以不传送的,data默认为空None,timeout默认为sock._GLOBAL_DEFAULT_TIMEOUT;
执行Urlopen方法之后,返回一个response对象,返回信息便保存在这里。
response对象有一个read()方法,可以返回获取到的网页内容。

urllib.request.Resquest

用Request类构建了一个完整的请求,增加了headers等一些信息.

首先,导入request模块

1
2
import urllib.request
from urllib.request import urlopen

具体程序如下:

1
2
3
4
5
6
7
headers = {'User-Agent' : 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0)Gecko/20100101 Firefox/29.0'}
req = urllib.request.Request(url=url,headers=headers)
try:
res = urllib.request.urlopen(req)
except urllib.error.URLError as e:
return e
page_content = res.read()

BeautifulSoup库

BeautifulSoup是用来从HTML或XML中提取数据的Python库。
导入:

1
from bs4 import BeautifulSoup

BeautifulSoup的第一个入参是文档,第二个入参是文档解析器,默认情况下的优先顺序是:lxml,html5lib,python标准库。其中只有lxml支持xml文档的解析。

1
2
page_content=BeautifulSoup(page_content,"lxml")
return page_content

其中,read() 方法用于从文件读取指定的字节数,如果未给定或为负则读取所有。
经过BeautifulSoup处理后,打印出来的就是网页的前端代码,它将一些其他的信息滤除掉了。

BeautifulSoup中find和find_all的用法

BeautifulSoup中内置了一些查找方法,最常用的是find()和find_all函数;
find_all得到所有符合条件的结果(形式:列表list),find只返回第一个符合条件的结果,所以find()后面可以直接接.text或者get_text()来获取标签中的文本。

注:find_all和findAll这两个方法是完全相同的,在新代码中,应该使用小写版本find_all,但是老的名字仍然可用。

SSL证书

现在随处可见https开头的网站,urllib2可以为HTTPS请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问,如:https://www.baidu.com/等...

如果没有CA认证的网站用urllib2访问的时候,会报出SSL(error)

所以,如果以后遇到这种网站,我们需要单独处理SSL证书,让程序忽略SSL证书验证错误,即可正常访问。
这时需要用到Python中的ssl模块。

1
2
import ssl
ssl._create_default_https_context=ssl._create_unverified_context

1.表示导入python ssl处理模块
2.表示忽略未经核实的SSL证书认证

HTML程序解析

通过BeautifulSoup处理后,我们得到了网页的HTML程序,下面要做的就是对HTML程序进行解析,提取出我们所需要的信息。

具体的解析方法,观察HTML代码寻找规律,对于牛客网实习官方信息而言,它的前端代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<li class="clearfix">
<div class="reco-job-main">
<div class="reco-job-pic">
<img src="https://uploadfiles.nowcoder.com/images/20180522/303498_1526990692890_0D6BF0A200B09382C4C32821CB2EDA28">
</div>
<div class="reco-job-cont">
<a href="/job/639?jobIds=2601" class="reco-job-title" target="_blank">软件开发工程师</a>
<div class="reco-job-com">
上海孝庸资产管理有限公司
</div>
</div>
<div class="reco-job-info">
<div class="">
<span class="nk-txt-ellipsis js-nc-title-tips job-address" data-title="上海"><i class="icon-map-marker"></i>上海</span>
<span><span class="ico-nb">&yen;</span>面议/天</span>
<span class="job-status-tag job-status-tag1">处理快</span>
</div>
<div class="reco-job-detail">
<span class="publisher-name js-nc-title-tips" title="上海孝庸资产管理有限公司">上海孝庸资产管理有限公司</span>
<span>34分钟前</span>
<div class="reco-job-status">
<span>简历处理率:100%</span>
<span>平均处理:1天</span>
</div>
</div>
</div>
</div>
</li>

首先,寻找出<li> <\li>标签,我们所需的信息都包含在这两个标签里面;
进一步分析,岗位信息和岗位链接信息都包含在class=”reco-job-title”的<a>标签里面,通过.get_text (一种提取文本信息的方法) 获取岗位信息;
通过.get(“href”) ( 返回指定键的值,如果不存在返回默认值 ) 获取岗位链接;

地点的获取:可以看出地点信息包含在:

1
<span class="nk-txt-ellipsis js-nc-title-tips job-address" data-title="上海"><i class="icon-map-marker"></i>上海</span>

因此,找到这个class对应的span,然后用get_text方法获取地点;
同样的方法,获取公司信息。

相应的python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def getJobInfo(page_content):
zhiwei=[]
company=[]
link=[]
data=[]
shixi_of = '🔴'+ '来自牛客网最新官方实习信息' + "\n" + '[机器喵自动获取,仅供参考]' + "\n" + "---------------------------------" + "\n"
data.append(shixi_of)
global i,j,k,m

job_li=page_content.findAll("li",{"class":"clearfix"})
# print(job_li)
for job_div in job_li:
job_zhiwei = job_div.findAll("a", {"class": "reco-job-title"})
for jobzw in job_zhiwei:
# zhiwei.append(jobzw.get_text())
global i
i='岗位:'+jobzw.get_text()+'\n'
link_1='https://www.nowcoder.com'+jobzw.get("href")
global k
k='详细信息:'+link_1+'\n'+'---------------------------------'
# link.append(link_1)
job_location=job_div.findAll("span",{"class":"nk-txt-ellipsis js-nc-title-tips job-address"})
for joblocation in job_location:
global m
m='地点:'+joblocation.get_text()+'\n'
job_company=job_div.findAll("div",{"class":"reco-job-com"})
for jobcom in job_company:
# company.append(jobcom.get_text())
global j
j='公司:'+jobcom.get_text().replace('\n','')+'\n'
data.append(i+j+m+k)

arr="".join(data)
# for h in data:
print(arr)
# print(h)
return data

range()方法和xrange()的区别

首先,程序中在获取每一页上面的信息时,用到了range方法循环url:

1
2
3
for i in range(1, 6):
url='https://www.nowcoder.com/job/center?type=1&page='+str(i)
getJobInfo(getPageContent(url))

range和xrange的区别

首先我们看看range: range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。
注意这里是生成一个序列。

xrange的用法与range相同,即xrange([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,他所不同的是xrange并不是生成序列,而是作为一个生成器,即他的数据生成一个取出一个。

所以相对来说,xrange比range性能优化很多,因为他不需要一下子开辟一块很大的内存,特别是数据量比较大的时候。

print问题

对于输出的信息,分别存在i,j,k,m中,以字符串的形式;
定义了一个data=[]数组,用来存储每次得到的信息

1
2
3
      data.append(i+j+m+k)
for h in data:
print(h)

最后的输出,是一条一条的,把每条信息都分开了(print出来并不明显,但是微信发送的时候消息就会很多)

1
2
3
4
5
6
7
8
🔴来自牛客网最新官方实习信息
[机器喵自动获取,仅供参考]
---------------------------------
岗位:游戏开发工程师(可实习可转正)
公司:4399游戏
地点:北京
详细信息:https://www.nowcoder.com/job/711?jobIds=2642
---------------------------------

如果想把所有的消息合为一条,经过查资料,找到了.join()方法,该方法用于将序列中的元素以指定的字符连接生成一个新的字符串。

str.join(元组、列表、字典、字符串)之后生成的只能是字符串;
所以,很多时候,可以用join()来转化为字符串;

1
2
arr="".join(data)
print(arr)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
🔴来自牛客网最新官方实习信息
[机器喵自动获取,仅供参考]
---------------------------------
岗位:游戏开发工程师(可实习可转正)
公司:4399游戏
地点:北京
详细信息:https://www.nowcoder.com/job/711?jobIds=2642
---------------------------------
岗位:软件开发工程师
公司:上海孝庸资产管理有限公司
地点:上海
详细信息:https://www.nowcoder.com/job/639?jobIds=2601
---------------------------------
岗位:百度核心搜索部机器学习算法实习生
公司:百度
地点:北京
详细信息:https://www.nowcoder.com/job/875?jobIds=2704
---------------------------------
岗位:办公软件C++研发实习生
公司:中标软件有限公司
地点:北京
详细信息:https://www.nowcoder.com/job/464?jobIds=2371
---------------------------------
岗位:大数据研发实习生
公司:北京小米科技有限责任公司
地点:北京
详细信息:https://www.nowcoder.com/job/867?jobIds=2703
---------------------------------