Python 网络爬虫 009 (编程) 经过正则表达式来获取一个网页中的全部的URL连接,并下载这些URL连接的源代码

经过 正则表达式 来获取一个网页中的全部的 URL连接,并下载这些 URL连接 的源代码

使用的系统:Windows 10 64位
Python 语言版本:Python 2.7.10 V
使用的编程 Python 的集成开发环境:PyCharm 2016 04
我使用的 urllib 的版本:urllib2html

注意: 我没这里使用的是 Python2 ,而不是Python3python


一 . 前言

经过以前两节(爬取一个网页 的网络爬虫解决爬取到的网页显示时乱码问题),咱们终于完成了最终的 download() 函数。
而且上上一节 ,咱们经过网站地图解析里面的URL的方式爬取了目标站点的全部网页。在 上一节,介绍一种方法来爬取一个网页里面全部的连接网页。这一节,咱们经过正则表达式来获取一个网页中的全部的URL连接,并下载这些URL连接的源代码。git


二 . 简介

到目前为止,咱们已经利用目标网站的结构特色实现了两个简单爬虫。只要这两个技术可用,就应当使用其进行爬取,由于这两个方法最小化了须要下载的网页数量。不过,对于一些网站,咱们须要让爬虫表现得更像普通用户:跟踪连接,访问感兴趣的内容。github

经过跟踪全部连接的方式,咱们能够很容易地下载整个网站的页面。可是这种方法会下载大量咱们并不须要的网页。例如,咱们想要从一个在线论坛中爬取用户帐号详情页,那么此时咱们只须要下载帐户页,而不须要下载 讨论轮贴的页面。本篇博客中的连接爬虫将使用正则表达式来肯定须要下载那些页面。web


三 . 初级代码

import re

def link_crawler(seed_url, link_regex):
    """Crawl from the given seed URL following links matched by link_regex """
    crawl_queue = [seed_url]
    while crawl_queue:
        url = crawl_queue.pop()
        html = download(url)
        # filter for links matching our regular expression
        for link in get_links(html):
            if re.match(link_regex, link):
                crawl_queue.append(link)

def get_links(html):
    """Return a list of links from html """
    # a regular expression to extract all links from the webpage 
    webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE)
    # list of all links from the webpage
    return webpage_regex.findall(html)

四 . 讲解初级代码

1 . 正则表达式

def link_crawler(seed_url, link_regex):

这个函数就是咱们要在外部使用的函数。功能:先下载 seed_url 网页的源代码,而后提取出里面全部的连接URL,接着对全部匹配到的连接URL与link_regex 进行匹配,若是连接URL里面有link_regex内容,就将这个连接URL放入到队列中,下一次 执行 while crawl_queue: 就对这个 连接URL 进行一样的操做。反反复复,直到 crawl_queue 队列为空,才退出函数。express


2 . 编程

get_links(html) 函数的功能:用来获取 html 网页中全部的连接URLapi


3 . 浏览器

webpage_regex = re.compile('<a[^>]+href=["\']'(.*?)["\']', re.IGNORECASE)

作了一个匹配模板,存在 webpage_regex 对象里面 。匹配<a href="xxx"> 这样的字符串,并提取出里面xxx的内容,这个xxx就是网址 URL


4 .

return webpage_regex.findall(html)

使用 webpage_regex 这个模板对 html 网页源代码匹配全部符合<a href="xxx"> 格式的字符串,并提取出里面的 xxx 内容。


详细的正则表达式的知识,请到这个网站了解:
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html


五 . 运行

先启动Python 终端交互指令,在PyCharm软件的Terminal窗口中 或者 在Windows 系统的DOS窗口中执行下面的命令:

C:\Python27\python.exe -i 1-4-4-regular_expression.py

执行link_crawler() 函数:

>>> link_crawler('http://example.webscraping.com', '/(index|view)')

输出:

Downloading:  http://example.webscraping.com
Downloading:  /index/1
Traceback (most recent call last):
  File "1-4-4-regular_expression.py", line 50, in <module>
    link_crawler('http://example.webscraping.com', '/(index|view)')
  File "1-4-4-regular_expression.py", line 36, in link_crawler
    html = download(url)
  File "1-4-4-regular_expression.py", line 13, in download
    html = urllib2.urlopen(request).read()
  File "C:\Python27\lib\urllib2.py", line 154, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python27\lib\urllib2.py", line 423, in open
    protocol = req.get_type()
  File "C:\Python27\lib\urllib2.py", line 285, in get_type
    raise ValueError, "unknown url type: %s" % self.__original
ValueError: unknown url type: /index/1

运行的时候,出现了错误。这个错误出在:下载 /index/1 URL时。这个 /index/1 是目标站点中的一个相对连接,就是完整网页URL 的路径部分,而没有协议和服务器部分。咱们使用download() 函数是没有办法下载的。在浏览器里浏览网页,相对连接是能够正常工做的,可是在使用 urllib2 下载网页时,由于没法知道上下文,因此没法下载成功。


七 . 改进代码

因此为了让urllib2 可以定为网页,咱们须要将相对连接转换为绝对连接,这样方可解决问题。
Python 里面有能够实现这个功能的模块:urlparse

下面对 link_crawler() 函数进行改进:

import urlparse
def link_crawler(seed_url, link_regex):
    """Crawl from the given seed URL following links matched by link_regex """
    crawl_queue = [seed_url]
    while crawl_queue:
        url = crawl_queue.pop()
        html = download(url)
        for link in get_links(html):
            if re.match(link_regex, link):
                link = urlparse.urljoin(seed_url, link)
                crawl_queue.append(link)

八 . 运行:

运行程序:

>>> link_crawler('http://example.webscraping.com', '/(index|view)')

输出:

Downloading:  http://example.webscraping.com
Downloading:  http://example.webscraping.com/index/1
Downloading:  http://example.webscraping.com/index/2
Downloading:  http://example.webscraping.com/index/3
Downloading:  http://example.webscraping.com/index/4
Downloading:  http://example.webscraping.com/index/5
Downloading:  http://example.webscraping.com/index/6
Downloading:  http://example.webscraping.com/index/7
Downloading:  http://example.webscraping.com/index/8
Downloading:  http://example.webscraping.com/index/9
Downloading:  http://example.webscraping.com/index/10
Downloading:  http://example.webscraping.com/index/11
Downloading:  http://example.webscraping.com/index/12
Downloading:  http://example.webscraping.com/index/13
Downloading:  http://example.webscraping.com/index/14
Downloading:  http://example.webscraping.com/index/15
Downloading:  http://example.webscraping.com/index/16
Downloading:  http://example.webscraping.com/index/17
Downloading:  http://example.webscraping.com/index/18
Downloading:  http://example.webscraping.com/index/19
Downloading:  http://example.webscraping.com/index/20
Downloading:  http://example.webscraping.com/index/21
Downloading:  http://example.webscraping.com/index/22
Downloading:  http://example.webscraping.com/index/23
Downloading:  http://example.webscraping.com/index/24
Downloading:  http://example.webscraping.com/index/25
Downloading:  http://example.webscraping.com/index/24
Downloading:  http://example.webscraping.com/index/25
Downloading:  http://example.webscraping.com/index/24
Downloading:  http://example.webscraping.com/index/25
Downloading:  http://example.webscraping.com/index/24

经过运行获得的结果,你能够看出来:虽然,如今能够下载网页没有出错,可是一样的网页会被不断的下载到。为何会这样?这是由于这些连接URL相互之间存在连接。若是两个网页之间相互都有对方的连接,那么对着这个程序,它会不断死循环下去。


因此,咱们还须要继续改进程序:避免爬取相同的连接,因此咱们须要记录哪些连接已经被爬取过,若是已经被爬取过了,就不在爬取它。

九 . 继续改进 link_crawler()函数:

def link_crawler(seed_url, link_regex):
    crawl_queue = [seed_url]
    # keep track which URL's have seen before
    seen = set(crawl_queue)
    while crawl_queue:
        url = crawl_queue.pop()
        html = download(url)
        for link in get_links(html):
            # check if link matches expected regex
            if re.match(link_regex, link):
                # form absolute link
                link = urlparse.urljoin(seed_url, link)
                # check if have already seen this link
                if link not in seen:
                    seen.add(link)
                    crawl_queue.append(link)

十 . 运行:

>>> link_crawler('http://example.webscraping.com', '/(index|view)')

输出:

Downloading:  http://example.webscraping.com
Downloading:  http://example.webscraping.com/index/1
Downloading:  http://example.webscraping.com/index/2
Downloading:  http://example.webscraping.com/index/3
Downloading:  http://example.webscraping.com/index/4
Downloading:  http://example.webscraping.com/index/5
Downloading:  http://example.webscraping.com/index/6
Downloading:  http://example.webscraping.com/index/7
Downloading:  http://example.webscraping.com/index/8
Downloading:  http://example.webscraping.com/index/9
Downloading:  http://example.webscraping.com/index/10
Downloading:  http://example.webscraping.com/index/11
Downloading:  http://example.webscraping.com/index/12
Downloading:  http://example.webscraping.com/index/13
Downloading:  http://example.webscraping.com/index/14
Downloading:  http://example.webscraping.com/index/15
Downloading:  http://example.webscraping.com/index/16
Downloading:  http://example.webscraping.com/index/17
Downloading:  http://example.webscraping.com/index/18
Downloading:  http://example.webscraping.com/index/19
Downloading:  http://example.webscraping.com/index/20
Downloading:  http://example.webscraping.com/index/21
Downloading:  http://example.webscraping.com/index/22
Downloading:  http://example.webscraping.com/index/23
Downloading:  http://example.webscraping.com/index/24
Downloading:  http://example.webscraping.com/index/25
Downloading:  http://example.webscraping.com/view/Zimbabwe-252
Downloading:  http://example.webscraping.com/view/Zambia-251
Downloading:  http://example.webscraping.com/view/Yemen-250
Downloading:  http://example.webscraping.com/view/Western-Sahara-249

如今这个程序就是一个很是完美的程序,它会爬取全部地点,而且可以如期中止。最终,完美获得了一个可用的爬虫。




总结:
这样,咱们就已经介绍了3种爬取一个站点或者一个网页里面全部的连接URL的源代码。这些只是初步的程序,接下来,咱们还可能会遇到这样的问题:
1 . 若是一些网站设置了 禁止爬取的URL,咱们为了执行这个站点的规则,就要按照它的 robots.txt 文件来设计爬取程序。
2 . 在国内是上不了google的,那么若是咱们想要使用代理的方式上谷歌,就须要给咱们的爬虫程序设置代理。
3 . 若是咱们的爬虫程序爬取网站的速度太快,可能就会被目标站点的服务器封杀,因此咱们须要限制下载速度。
4 . 有一些网页里面有相似日历的东西,这个东西里面的每个日期都是一个URL连接,咱们有不会去爬取这种没有意义的东西。日期是无止境的,因此对于咱们的爬虫程序来讲,这就是一个爬虫陷阱,咱们须要避免陷入爬虫陷阱。

咱们须要解决上这4个问题。才能获得最终版本的爬虫程序。

相关文章
相关标签/搜索