Python网络数据采集一书中的错误

阅读《Python网络数据采集》(中文版)一书的过程中,发现了一个小错误,第28页‘冒号’被翻译成了分号,但代码是对的,无伤大雅。但是我在运行后面第35页的代码过程中却遇到了一些问题。
我虽然有原书的电子版,但是在复制到博客的过程中代码总是很凌乱,就不往上贴了,我翻了一下作者的github账户,找到了这一部分的代码,果然已经和原书不一样了,估计是当时作者自己也写错了(汗)。
原书的代码错误在于:

  1. getInternalLinks()函数中得到的InternalLinks是没有’http://’的,如果在一个网站的页面中没有找到ExternalLinks,就会从这个网页中找指向本网站其他页面的链接,这时候问题就来了,Python的urllib库中的urlopen()函数在打开没有'http://'的链接时就会抛出URLError异常,然后‘咔!’的一声程序就停了,只留下我一脸蒙逼的盯着屏幕。。。
  2. 同是getInternalLinks()函数,在查找内链时使用的正则表达式为'(/|.*' + includeUrl + ')' 也许是这个条件过于严格,可能会一个内链也得不到,这样在getRandomExternalLink() 函数中getRandomExternalLink(internalLinks[random.randint(0,len(internalLinks) - 1)]) 这里就会出现内链列表长度为零,这时就会抛出一个ValueError 异常,程序崩溃
  3. 上面两个算是严重一点的,还有一个小的问题是没有处理HTTPError 异常的机制,这种情况主要发生在爬取速度过快服务器断开连接,还有连接超时的时候。遇到这种情况程序也会崩溃,不过作者在书中已经声明了因为写书的空间限制就没有把异常处理的代码写上。

在我被原书代码搞得很纠结的时候我并没有想到去github找一下作者的代码,而是尝试着自己解决了一下,最终算是勉强打上了几个丑陋的补丁吧。下面是针对前面三个问题的处理方式:

  1. 既然得到的内链没有'http://'我们可以人为的把它加上,首先要知道得到的内链可能是以./ 开头的,所以我们要先把它们去掉,这时候正则表达式就出场了,因为对Python的语法并不是很熟悉,我还特别去谷歌了一下,最终找到了这个函数re.sub('.|/+','',link.attrs['href']),然后再在前面加上'http://'就可以了。
  2. 前面说的第二和第三个错误都没有什么好的解决方案,我只想到了一个比较笨的方法,就是用try 语句来处理一下异常。

这样至少不会报错了,最终我的代码如下:

from urllib.request import urlopen
from urllib.error import HTTPError
from urllib.error import URLError
from bs4 import BeautifulSoup
import random
import datetime
import re

pages = set()
random.seed(datetime.datetime.now())

def getInternalLinks(bsObject,includeUrl):
        internalLinks = []
        for link in bsObject.findAll('a',href = re.compile('^(/|.{0,2}' + includeUrl + ')')):
                if link.attrs['href'] is not None:
                        href = 'http://' + re.sub('^(.|/)+','',link.attrs['href'])
                        if href not in internalLinks:
                                internalLinks.append(href)
        return(internalLinks)

def splitAddress(address):
    addressParts = address.replace('http://','').split('/')
    return(addressParts)

def getExternalLinks(bsObject,excludeUrl):
    externalLinks = []
    for link in bsObject.findAll('a',{'href': re.compile('^(http)((?!' + excludeUrl + ').)*$')}):
        if link.attrs['href'] is not None:
            href = link.attrs['href']
            if href not in externalLinks:
                externalLinks.append(href)
    return(externalLinks)

def getRandomExternalLink(startingPage):
        html = urlopen(startingPage)
        bsObject = BeautifulSoup(html,'html.parser')
        externalLinks = getExternalLinks(bsObject,splitAddress(startingPage)[0])
        if len(externalLinks) == 0:
                internalLinks = getInternalLinks(bsObject,splitAddress(startingPage)[0])
                return(getRandomExternalLink(internalLinks[random.randint(0,len(internalLinks) - 1)]))
        else:
                return(externalLinks[random.randint(0,len(externalLinks) - 1)])

def followExternalOnly(startingSite):
        externalLink = getRandomExternalLink(startingSite)
        print('随机外链是: ' + externalLink)
        try:
            followExternalOnly(externalLink)
        except (HTTPError,ValueError,URLError):
            followExternalOnly(startingSite)

followExternalOnly('http://www.xmu.edu.cn/')

--------------------------分割线----------------------------------
看了作者github上的代码我觉得学习Python我还有很长的路要走
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值