Python爬虫编程思想:实战案例:抓取所有的网络资源

Posted 蒙娜丽宁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python爬虫编程思想:实战案例:抓取所有的网络资源相关的知识,希望对你有一定的参考价值。

       Python爬虫编程思想(7):实战案例:抓取博客文章列表

         到现在为止,我们已经对网络爬虫涉及到的基本知识有了一个初步的了解。本文会编写一个简单的爬虫应用,以便让读者对爬虫有一个基本的认识。本节要编写的爬虫属于全网爬虫类别,但我们肯定不会抓取整个互联网的资源。所以本节会使用7个html文件来模拟互联网资源,并将这7个HTML文件放在本地的nginx服务器的虚拟目录,以便抓取这7个HTML文件。

        全网爬虫要至少有一个入口点(一般是门户网站的首页),然后会用爬虫抓取这个入口点指向的页面,接下来会将该页面中所有链接节点(a节点)中href属性的值提取出来。这样会得到更多的Url,然后再用同样的方式抓取这些Url指向的HTML页面,再提取出这些HTML页面中a节点的href属性的值,然后再继续,直到所有的HTML页面都被分析完为止。只要任何一个HTML页面都是通过入口点可达的,使用这种方式就可以抓取所有的HTML页面。这很明显是一个递归过程,下面就用伪代码来描述这一递归过程。

        从前面的描述可知,要实现一个全网爬虫,需要下面两个核心技术。

  • 下载Web资源(html、css、js、json)
  • 分析Web资源

        假设下载资源通过download(url)函数完成,url是要下载的资源链接。download函数返回了网络资源的文本内容。analyse(html)函数用于分析Web资源,html是download函数的返回值,也就是下载的HTML代码。analyse函数返回一个列表类型的值,该返回值包含了HTML页面中所有的URL(a节点href属性值)。如果HTML代码中没有a节点,那么analyse函数返回空列表(长度为0的列表)。下面的drawler函数就是下载和分析HTML页面文件的函数,外部程序第1次调用crawler函数时传入的URL就是入口点HTML页面的链接。

def crawler(url)
{
    # 下载url指向的HTML页面
    html = download(url)
    # 分析HTML页面代码,并返回该代码中所有的URL
    urls = analyse(html)
    # 对URL列表进行迭代,对所有的URL递归调用crawler函数
    for url in urls
    {
        crawler(url)
    }
}
# 外部程序第一次调用crawler函数,http://localhost/files/index.html就是入口点的URL
crawler('http://localhost/files/index.html ')

        本节的例子需要使用到nginx服务器,下面是nginx服务器的安装方法。

        nginx是免费开源的,下载地址是https://nginx.org/en/download.html。如果读者使用的是Windows平台,直接下载nginx压缩包(一个zip压缩文件),直接解压即可。如果读者使用的是Mac OS X或Linux平台,需要使用下面的方式编译nginx源代码,并安装nginx。

        进入nginx源代码目录,然后执行下的命令配置nginx。

./configure --prefix=/usr/local/nginx

上面的配置指定了nginx的安装目录是/usr/local/nginx。

接下来执行下面的命令编译和安装nginx。

make && make install

        如果安装成功,会在/usr/local目录下看到nginx目录。

        下面会使用递归的方式编写了一个全网爬虫,该爬虫会从本地的nginx服务器(其他Web服务器也可以)抓取所有的HTML页面,并通过正则表达式分析HTML页面,提取出a节点的href属性值,最后将获得的所有URL输出到Console。

        在编写代码之前,先要准备一个Web服务器(Nginx、Apache、IIS都可以),并建立一个虚拟目录。Nginx默认的虚拟目录路径是根目录>/html。然后准备7个HTML文件,这些HTML文件的名称和关系如图1所示。

        很明显,index.html文件是入口点,从index.html文件可以导向a.html、b.html和c.html。从a.html可以导向aa.html和bb.html,从c.html可以导向cc.html。也就是说,只要从index.html文件开始抓取,就可以成功抓取所有的HTML文件。

        现在将这7个HTML文件都放在根目录>/html/files目录下,然后按下面的代码编写爬虫程序。

        7个HTML文件所在的目录位置是src/firstspider/files

        下面是本例的7个HTML文件的代码,爬虫会抓取和分析这7个HTML文件的代码。

<!--  index.html  入口点  -->
<html>
    <head><title>index.html</title></head>
    <body>
        <a href='a.html'>first page</a>
        <p>
        <a href='b.html'>second page</a>
        <p>
        <a href='c.html'>third page</a>
        <p>
    </body>
</html>
<!--  a.html  -->
<html>
    <head><title>a.html</title></head>
    <body>
        <a href='aa.html'>aa page</a>
        <p>
        <a href='bb.html'>bb page</a>
    </body>
</html>
<!--  b.html  -->
<html>
    <head><title>b.html</title></head>
    <body>
	   b.html
    </body>
</html>
<!--  c.html  -->
<html>
    <head><title>c.html</title></head>
    <body>
        <a href='cc.html'>cc page</a>
    </body>
</html>
<!--  aa.html  -->
<html>
    <head><title>aa.html</title></head>
    <body>
    aa.html
    </body>
</html>
<!--  bb.html  -->
<html>
    <head><title>bb.html</title></head>
    <body>
    bb.html
    </body>
</html>
<!--  cc.html  -->
<html>
    <head><title>cc.html</title></head>
    <body>
    cc.html
    </body>
</html>

从上面的代码可以看到,b.html、aa.html、bb.html和cc.html文件中并没有a节点,所以这4个HTML文件是递归的终止条件。

下面是基于递归算法的爬虫的代码。

from urllib3 import *
from re import *
http = PoolManager()
disable_warnings()
# 下载HTML文件
def download(url):
result = http.request('GET', url)
# 将下载的HTML文件代码用utf-8格式解码成字符串
    htmlStr = result.data.decode('utf-8')
    # 输出当前抓取的HTML代码
    print(htmlStr)
    return htmlStr
# 分析HTML代码
def analyse(htmlStr):
    # 利用正则表达式获取所有的a节点,如<a href='a.html'>a</a>
    aList = findall('<a[^>]*>',htmlStr)
result = []
# 对a节点列表进行迭代
    for a in aList:
        # 利用正则表达式从a节点中提取出href属性的值,如<a href='a.html'>中的a.html
        g = search('href[\\s]*=[\\s]*[\\'"]([^>\\'""]*)[\\'"]',a)
        if g != None:
            # 获取a节点href属性的值,href属性值就是第1个分组的值
url = g.group(1)
# 将Url变成绝对链接 
url = 'http://localhost/files/' + url
# 将提取出的Url追加到result列表中
            result.append(url)
    return result
# 用于从入口点抓取HTML文件的函数
def crawler(url):
    # 输出正在抓取的Url
print(url)
# 下载HTML文件 
html = download(url)
# 分析HTML代码
urls = analyse(html)
# 对每一个Url递归调用crawler函数
    for url in urls:
        crawler(url)
# 从入口点Url开始抓取所有的HTML文件
crawler('http://localhost/files')

在运行程序之前,要先启动nginx服务,启动方式如下:

  • Windows:双击nginx.exe文件。
  • macOS和Linux:在终端进入nginx根目录,执行sudo sbin/nginx命令。

程序运行结果如图2所示。

    Python爬虫编程思想(7):实战案例:抓取博客文章列表

以上是关于Python爬虫编程思想:实战案例:抓取所有的网络资源的主要内容,如果未能解决你的问题,请参考以下文章

Python爬虫编程思想(62): 项目实战:抓取酷狗网络红歌榜

Python爬虫编程思想(62): 项目实战:抓取酷狗网络红歌榜

Python爬虫编程思想(36):项目实战-抓取斗破小说网的目录和全文

Python爬虫编程思想(143):项目实战:多线程和多进程爬虫

Python爬虫编程思想(143):项目实战:多线程和多进程爬虫

Python爬虫编程思想(92):项目实战:抓取京东图书评价