自己动手就能制作爬虫程序!内含完整代码演示

自己动手就能制作爬虫程序!内含完整代码演示第3章 我的第一个爬虫程序

了解了爬虫原理和网页构造后,我们知道了爬虫的任务就是两件事情:请求网页和解析提取信息。本章就从这两个方面入手,

大家好,欢迎来到IT知识分享网。

自己动手就能制作爬虫程序!内含完整代码演示


第3章 我的第一个爬虫程序

了解了爬虫原理和网页构造后,我们知道了爬虫的任务就是两件事情:请求网页和解析提取信息。本章就从这两个方面入手,首先安装请求和解析网页的Python第三方库,之后将手把手教读者编写一个简单的爬虫程序。

本章涉及的主要知识点如下。

·Python第三方库:学会Python第三方库的概念及安装方法。

·Requests库:学会Requests库的使用原理和方法。

·BeautifulSoup库:学会BeautifulSoup库的使用原理和方法。

·Requests和BeautifulSoup库组合应用:通过本章最后给出的实例,演示如何利用这两大库进行爬虫的方法和技巧。

3.1 Python第三方库

本节主要介绍Python第三方库的基本概念和安装方法,通过第三库的使用,才能让爬虫起到事半功倍的效果。

3.1.1 Python第三方库的概念

Python之所以强大并逐渐流行起来,一部分原因要归功于Python强大的第三方库。这样用户就不用了解底层的思想,用最少的代码写出最多的功能。就像制造自行车一样,需要:

·铁矿石;

·橡胶;

·扳手等工具。

如果没使用第三库的话,就需要从原始材料开始,一步步制造下去,一个车轮子都不知道要造多久呢!而使用第三方库就不一样了,车轮子和车身都已经制造好了,拼接一下就可以使用了(有些车直接就可以用了)。这种拿来即用的就是Python第三方库。

3.1.2 Python第三方库的安装方法

既然Python第三方库如此好用,那么本节就介绍如何安装这些方便的第三方库。

自己动手就能制作爬虫程序!内含完整代码演示注意:安装步骤以Windows 7系统为准。

1.在PyCharm中安装

(1)打开PyCharm,在菜单栏中选择File∣Defalut Settings命令。

(2)在弹出的对话框中选择左侧的Project Interpreter选项,在窗口右方选择Python环境。

(3)单击加号按钮添加第三方库。

(4)然后输入第三方库名称,选中需下载的库。

(5)勾选Install to users site复选框,然后单击Install Package按钮。操作过程如图3.1和图3.2所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.1 PyCharm中安装第三库步骤1

自己动手就能制作爬虫程序!内含完整代码演示

图3.2 PyCharm中安装第三库步骤2

在安装完成后,PyCharm会有成功提示。读者也可以通过展开Project Interpreter选项查看已经安装的库,单击减号按钮可以卸载不需要的库。

2.在PIP中安装

在安装Python后,PIP也会同时进行安装,我们可以在命令行cmd中输入:

pip --version

如果出现下面提示,则表示PIP成功安装。

pip 9.0.1 from D:\anaconda\lib\site-packages (python 3.6)

在PIP成功安装之后,在命令行cmd中输入以下代码即可下载第三方库:

pip3 install packagename
#packagename为安装库的名称,在这里输入pip3 install beautifulsoup4即可下载beautifulsoup4库了。

自己动手就能制作爬虫程序!内含完整代码演示注意:如果为Python 2,PIP 3改为PIP。

安装完后有提示:

Successfully installed packagename

3.下载whl文件

有时候前面的两种方法安装会出现问题,可能是由于网络原因,也可能是包的依赖关系而引起的,这时候就需要手动安装,这种方法最稳妥。

(1)进入http://www.lfd.uci.edu/~gohlke/pythonlibs/,搜索lxml库,然后单击下载到本地,如图3.3所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.3 下载whl文件

(2)然后在命令行输入:

pip3 install wheel

(3)等待执行,执行成功后在命令行输入:

cd D:\python\ku
#后面为下载whl 文件的路径

(4)最后在命令行输入:

pip3 install lxml-3.7.2-cp35-cp35m-win_amd64.whl
# lxml-3.7.2-cp35-cp35m-win_amd64.whl 是你下载的文件的完整路径名

这样就可以下载库到本地了,通过whl文件,可以自动安装依赖的包。

自己动手就能制作爬虫程序!内含完整代码演示注意:推荐第2种和第3种安装第三方库的方法,当第2种方法报错时可选择第3种方法。

3.1.3 Python第三方库的使用方法

当成功安装Python第三方库后,就可通过下面的方法导入并使用第三方库了:

import xxxx
#xxxx 为导入的库名,例如import requests

自己动手就能制作爬虫程序!内含完整代码演示注意:导入BeautifulSoup库的写法为from bs4import BeautifulSoup。

3.2 爬虫三大库

讲过了Requests、Lxml和BeautifulSoup库的安装后,本节将依次讲解各个库的说明和使用方法,然后一起完成读者的第一个爬虫小程序。

3.2.1 Requests库

Requests库的官方文档指出:让HTTP服务人类。细心的读者会发现,Requests库的作用就是请求网站获取网页数据的。让我们从简单的实例开始,讲解Requests库的使用方法。

import requests
res = requests.get('http://bj.xiaozhu.com/')#网站为小猪短租网北京地区网址
print(res)
#pycharm中返回结果为<Response [200]>,说明请求网址成功,若为404,400则请求网址失败
print(res.text)
#pycharm部分结果如图3.4所示

自己动手就能制作爬虫程序!内含完整代码演示

图3.4 打印网页源代码

这时打开Chrome浏览器,进入http://bj.xiaozhu.com/,在空白处右击,在弹出的快捷菜单中选择“查看网页源代码”命令,可以看到代码返回的结果就是网页的源代码。

有时爬虫需要加入请求头来伪装成浏览器,以便更好地抓取数据。在Chrome浏览器中按F12键打开Chrome开发者工具,刷新网页后找到User-Agent进行复制,如图3.5所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.5 复制请求头

请求头的使用方法:

import requests
headers = {
    User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
res = requests.get('http://bj.xiaozhu.com/',headers=headers)            #get方法加入请求头
print(res.text)

Requests库不仅有get()方法,还有post()等方法。post()方法用于提交表单来爬取需要登录才能获得数据的网站,这部分内容会在后面章节中学习,这里不再赘述。学习get()方法足够我们爬取大部分的网站了。

Requests库请求并不会“一帆风顺”,当遇到一些情况时,Requests库会抛出错误或者异常,Requests库的错误和异常主要有以下4种。

·Requests抛出一个ConnectionError异常,原因为网络问题(如DNS查询失败、拒绝连接等)。

·Response.raise_for_status()抛出一个HTTPError异常,原因为HTTP请求返回了不成功的状态码(如网页不存在,返回404错误)。

·Requests抛出一个Timeout异常,原因为请求超时。

·Requests抛出一个TooManyRedirects异常,原因为请求超过了设定的最大重定向次数。

所有Requests显式抛出的异常都继承自requests.exceptions.RequestException,当发现这些错误或异常进行代码修改重新再来时,爬虫的程序又开始重新运行了,爬取到的数据又会重新爬取一次,这对于爬虫的效率和质量来说都是不利的。这时,便可通过Python中的try来避免异常了,具体使用方法如下:

import requests
headers = {
    User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
res = requests.get('http://bj.xiaozhu.com/',headers=headers)
try:
    print(res.text)
except ConnectionError:                 #出现错误会执行下面的操作
    print('拒绝连接')

通过try和except,如果请求成功了,会打印网页的源代码。如果请求出现了ConnectionError异常,则会打印“拒绝连接”,这样程序就不会报错,而是给编程者一个提示,不会影响下面代码的运行。

3.2.2 BeautifulSoup库

BeautifulSoup库是一个非常流行的Python模块。通过BeautifulSoup库可以轻松地解析Requests库请求的网页,并把网页源代码解析为Soup文档,以便过滤提取数据。

import requests
from bs4 import BeautifulSoup
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
res = requests.get('http://bj.xiaozhu.com/',headers=headers)
soup = BeautifulSoup(res.text,'html.parser')            #对返回的结果进行解析
print(soup.prettify())

输出的结果如图3.6所示,看上去与Requests库请求返回的网页源代码类似,但通过BeautifulSoup库解析得到的Soup文档按照标准缩进格式的结构输出,为结构化的数据,为数据的过滤提取做好准备。

自己动手就能制作爬虫程序!内含完整代码演示

图3.6 解析Soup文档

BeautifulSoup库除了支持Python标准库中的HTML解析器外,还支持一些第三方的解析器。如表3.1中列出了BeautifulSoup库的主要解析器及相应的优缺点。

表3.1 BeautifulSoup库解析器

自己动手就能制作爬虫程序!内含完整代码演示

自己动手就能制作爬虫程序!内含完整代码演示注意:BeautifulSoup库官方推荐使用lxml作为解析器,因为效率更高。

解析得到的Soup文档可以使用find()和find_all()方法及selector()方法定位需要的元素了。find()和find_all()两个方法用法相似,BeautifulSoup文档中对这两个方法的定义是这样的:

find_all(tag, attibutes, recursive, text, limit, keywords)
find(tag, attibutes, recursive, text, keywords)

常用的是前两个参数,熟练运用这两个参数,就可以提取出想要的网页信息。

1.find_all()方法

soup.find_all('div',  "item")  ##查找div标签,class="item"
soup.find_all('div', class='item') 
soup.find_all('div', attrs={"class": "item"}) # attrs 参数定义一个字典参数来搜索包含特殊属性的tag

2.find()方法

find()方法与find_all()方法类似,只是find_all()方法返回的是文档中符合条件的所有tag,是一个集合(class’bs4.element.ResultSet’),find()方法返回的一个Tag(class’bs4.element.Tag’)。

3.selector()方法

soup.selector(div.item > a > h1)              #括号内容通过Chrome复制得到

该方法类似于中国>湖南省>长沙市,从大到小,提取需要的信息,这种方式可以通过Chrome复制得到,如图3.7所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.7 复制selector()方法

(1)鼠标定位到想要提取的数据位置,右击,在弹出的快捷菜单中选择“检查”命令。

(2)在网页源代码中右击所选元素。

(3)在弹出的快捷菜单中选择Copy selector。这时便能得到:

#page_list > ul > li:nth-child(1) > div.result_btm_con.lodgeunitname > span.result_price > i
通过代码即可得到房子价格:
import requests
from bs4 import BeautifulSoup                   #导入相应的库文件
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}                                                                               #请求头
res = requests.get('http://bj.xiaozhu.com/',headers=headers)    #请求网页
soup = BeautifulSoup(res.text,'html.parser')                                    #解析数据
price = soup.select('#page_list > ul > li:nth-of-type(1) > div.result_
btm_con. lodgeunitname > span.result_price > i')                                                                                                                          #定位元素位置并通过selector方法提取
print(price)

结果是会在屏幕上打印[<i>898</i>]标签。

自己动手就能制作爬虫程序!内含完整代码演示注意:li:nth-child(1)在Python中运行会报错,需改为li:nth-of-type(1)。

此时的li:nth-of-type(1)为选择的一个价格,为了做短租房的平均价格分析,当然是要把所有的房租价格全部提取出来。把selector改为:

#page_list > ul > li > div.result_btm_con.lodgeunitname > span.result_price > i

就可以得到整个页面的所有价格,这样提取的信息为列表,可以通过循环分别打印出来也可以存储起来。

import requests
from bs4 import BeautifulSoup
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
res = requests.get('http://bj.xiaozhu.com/',headers=headers)
soup = BeautifulSoup(res.text,'html.parser')
prices = soup.select('#page_list > ul > li > div.result_btm_con. lodgeunitname > span.result_price > i') #此时prices为列表,需循环遍历
for price in prices:
      print(price)

代码运行的结果如图3.8所示。

细心的读者会发现,提取的信息为[<i>898</i>]这种标签,而读者只需要其中的数据,这时用get_text()方法即可获得中间的文字信息。

import requests
from bs4 import BeautifulSoup
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 
    (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}
res = requests.get('http://bj.xiaozhu.com/',headers=headers)
soup = BeautifulSoup(res.text,'html.parser')
prices = soup.select('#page_list > ul > li > div.result_btm_con. lodgeunitname > span.result_price > i')
for price in prices:
      print(price.get_text())                   通过get_text()方法获取文字信息

代码运行的结果如图3.9所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.8 提取多个元素

自己动手就能制作爬虫程序!内含完整代码演示

图3.9 提取标签文本

这时程序就已经爬取了一页中所有的房价信息,但该网站有多个网页,这时就需要构造URL列表,详细方法见本章中的综合实例。

3.2.3 Lxml库

Lxml库是基于libxm12这一个XML解析库的Python封装。该模块使用C语言编写,解析速度比BeautifulSoup更快,具体的使用方法将在之后的章节中讲解。

3.3 综合案例1——爬取北京地区短租房信息

本节将利用Requests和BeautifulSoup第三方库,爬取小猪短租网北京地区短租房的信息。

3.3.1 爬虫思路分析

(1)本节爬取小猪短租网北京地区短租房13页的信息。通过手动浏览,以下为前4页的网址:

http://bj.xiaozhu.com/
http://bj.xiaozhu.com/search-duanzufang-p2-0/
http://bj.xiaozhu.com/search-duanzufang-p3-0/
http://bj.xiaozhu.com/search-duanzufang-p4-0/

然后把第一页的网址改为http://bj.xiaozhu.com/search-duanzufang-p1-0/后也能正常浏览,因此只需更改p后面的数字即可,以此来构造出13页的网址。

(2)本次爬虫在详细页面中进行,因此先需爬取进入详细页面的网址链接,进而爬取数据。

(3)需要爬取的信息有:标题、地址、价格、房东名称、房东性别和房东头像的链接,如图3.10所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.10 需获取的网页信息

3.3.2 爬虫代码及分析

爬虫代码如下:

01       from bs4 import BeautifulSoup
02      import requests
03      import time                                                     #导入相应的库文件
04      
05      headers = {
06          'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
07          (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
08      }                                                                       #加入请求头
09      
10      def judgment_sex(class_name):           #定义判断用户性别的函数
11        if class_name == ['member_ico1']:
12            return '女'
13        else:
14            return  '男'
15      
16      def get_links(url):                                     #定义获取详细页URL的函数
17          wb_data = requests.get(url,headers=headers)
18          soup = BeautifulSoup(wb_data.text,'lxml')
19          links = soup.select('#page_list > ul > li > a')    #links为URL列表
20          for link in links:
21              href = link.get("href")
22              get_info(href)                          #循环出的URL,依次调用get_info()函数
23      
24      def get_info(url):                                      #定义获取网页信息的函数
25          wb_data = requests.get(url,headers=headers)
26          soup = BeautifulSoup(wb_data.text,'lxml')
27          tittles = soup.select('div.pho_info > h4')
28          addresses = soup.select('span.pr5')
29          prices = soup.select('#pricePart > div.day_l > span')
30          imgs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_
            pic > a > img')
31          names = soup.select('#floatRightBox > div.js_box.clearfix > div.w_
            240 > h6 > a')
32          sexs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_
            pic > div')
33          for tittle, address, price, img, name, sex in zip(tittles,addresses,
            prices,imgs,names,sexs):
34              data = {
35                  'tittle':tittle.get_text().strip(),
36                  'address':address.get_text().strip(),
37                  'price':price.get_text(),
38                  'img':img.get("src"),
39                  'name':name.get_text(),
40                  'sex':judgment_sex(sex.get("class"))
41              }
42              print(data)                                     #获取信息并通过字典的信息打印
43      
44      if __name__ == '__main__':                      #为程序的主入口
45          urls = ['http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format
            (number) for number in
46      range(1,14)]                                            #构造多页URL
47          for single_url in urls:
48              get_links(single_url)           #循环调用get_links()函数
49              time.sleep(2)                           #睡眠2秒

程序运行的部分结果如图3.11所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.11 程序运行结果

代码分析:

(1)第1~3行导入程序需要的库,Requests库用于请求网页获取网页数据。BeautifulSoup用于解析网页数据。time库的sleep()方法可以让程序暂停。

(2)第5~8行通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。

(3)第16~22行定义了get_links()函数,用于获取进入详细页的链接。

传入URL后,进行请求和解析。通过Chrome浏览器的“检查”并“Copy selector”,可以找到进入详细页的URL链接,但URL链接并不是嵌套在标签中,而是在标签的属性信息中,如图3.12所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.12 URL链接位置

前面说到可用get_text()方法获取标签中的文本信息,但标签中的属性信息需要通过get(’attr’)方法获取得到,如图3.12所示,URL链接在href中,这时用get(’href’)便可得到网页的URL。

最后调用get_info()函数,转入的参数为获取到的网页详细页的链接。

(4)第24~42行定义get_info()函数,用于获取网页信息并输出信息。

传入URL后,进行请求和解析。通过Chrome浏览器的“检查”并“Copy selector”,获取相应的信息,由于信息数据为列表数据结构,可以通过多重循环,构造出字典数据结构,输出并打印出来。

自己动手就能制作爬虫程序!内含完整代码演示注意:字典中的sex调用了judgment_sex()函数。

(5)第10~14行定义judgment_sex()函数,用于判断房东的性别。

10       def judgment_sex(class_name):
11        if class_name == ['member_ico1']:
12            return '女'
13        else:
14            return  '男'

如图3.13所示,可以看出房东的性别区分。

自己动手就能制作爬虫程序!内含完整代码演示

图3.13 房东性别判断

在图中所示区域通过Chrome浏览器的“检查”可以发现,女房东的信息为<div class=”member_ico1″></div>,男房东的信息为<div class=”member_ico”></div>,这时就可以通过class属性来判断房东的性别。

(6)第44~49行为程序的主入口,通过对网页URL的观察,利用列表的推导式构造13个URL,并依次调用get_links()函数,time.sleep(2)的意思是每循环一次,让程序暂停2秒,防止请求网页频率过快而导致爬虫失败。

3.4 综合案例2——爬取酷狗TOP500的数据

本节将利用Requests和BeautifulSoup第三方库,爬取酷狗网榜单中酷狗TOP500的信息。

3.4.1 爬虫思路分析

(1)本节爬取的内容为酷狗榜单中酷狗TOP500的音乐信息,如图3.14所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.14 酷狗TOP500界面

(2)网页版酷狗不能手动翻页进行下一步的浏览,但通过观察第一页的URL:

http://www.kugou.com/yy/rank/home/1-8888.html

这里尝试把数字1换为数字2,再进行浏览,恰好返回的是第2页的信息(如图3.15所示)。进行多次尝试后,发现更换不同数字即为不同页面,因此只需更改home/后面的数字即可。由于每页显示的为22首歌曲,所以总共需要23个URL。

自己动手就能制作爬虫程序!内含完整代码演示

图3.15 第2页URL

(3)需要爬取的信息有排名情况、歌手、歌曲名和歌曲时间,如图3.16所示。

自己动手就能制作爬虫程序!内含完整代码演示

图3.16 需获取的网页信息

3.4.2 爬虫代码及分析

爬虫代码如下:

01       import requests
02      from bs4 import BeautifulSoup
03      import time                                                     #导入相应的库文件
04      
05      headers = {
06          'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
07          (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
08      }                                                                               #加入请求头
09      
10      def get_info(url):                                              #定义获取信息的函数
11          wb_data = requests.get(url,headers=headers)
12          soup = BeautifulSoup(wb_data.text,'lxml')
13          ranks = soup.select('span.pc_temp_num')
14          titles = soup.select('div.pc_temp_songlist > ul > li > a')
15          times = soup.select('span.pc_temp_tips_r > span')
16          for rank,title,time in zip(ranks,titles,times):
17              data = {
18                  'rank':rank.get_text().strip(),
19                  'singer':title.get_text().split('-')[0],
20                  'song':title.get_text().split('-')[0],      #通过split获取歌手
                                                                 和歌曲信息
21                  'time':time.get_text().strip()
22              }
23              print(data)                                             获取爬虫信息并按字典格式打印
24      
25      if __name__ == '__main__':                              #程序主入口
26          urls = ['http://www.kugou.com/yy/rank/home/{}-8888.html'.format
            (str(i)) for i in 
27      range(1,24)]                                                    #构造多页URL
28          for url in urls:
29              get_info(url)                                   #循环调用get_info()函数
        time.sleep(1)                                           #睡眠1秒

程序运行的部分结果如图3.17所示。

代码分析:

(1)第1~3行导入程序需要的库,Requests库用于请求网页获取网页数据,BeautifulSoup用于解析网页数据,time库的sleep()方法可以让程序暂停。

(2)第5~8行通过Chrome浏览器的开发者工具,复制User-Agent,用于伪装为浏览器,便于爬虫的稳定性。

(3)第10~23行定义get_info()函数,用于获取网页信息并输出信息。

传入URL后,进行请求和解析。通过Chrome浏览器的“检查”并“Copy selector”,获取相应的信息,由于信息数据为列表数据结构,因此可以通过多重循环,构造出字典数据结构,输出并打印出来。

自己动手就能制作爬虫程序!内含完整代码演示

图3.17 程序运行结果

自己动手就能制作爬虫程序!内含完整代码演示注意:本案例并未完全使用“Copy selector”的全部信息,由于有些标签是固定的,因此选用部分路径即可。

(4)第25~29行为程序的主入口。通过对网页URL的观察,利用列表的推导式构造23个URL,并依次调用get_info()函数,time.sleep(1)的意思是每循环一次,让程序暂停1秒,防止请求网页频率过快而导致爬虫失败。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/52872.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信