• 《用python写网络爬虫》 编写第一个网络爬虫


    为了抓取网站,我们首先需要下载包含有感兴趣数据的网页,该过程一般被称为爬取“crawing”。爬取一个网站有很多种方法,而选用哪种方法更加合适,则取决于目标网站的结构。本章中,首先会探讨如何安全地下载网页,然后会介绍如下3种爬取网站的常见方法:

    • 爬取网站地图
    • 遍历每个网页的数据库ID
    • 跟踪网页链接

    下载网页

      想要爬取网页,我们首先需要将其下载下来。下面的示例脚本使用python的urllib2模块下载URL。

    import  urllib2
    def  download(url):
      return  urllib2.urlopen(url).read()

    当传入URL参数时,该函数将会下载网页并返回其HTML。不过,这个代码存在一个问题,即当下在网页时,我们可能会遇到一些无法控制的错误,比如请求的页面可能不存在。此时,urllib2会抛出异常,然后退出脚本。安全起见,下面再给出一个更健壮的版本,可以捕获这些异常。

    import urllib2
    
    def download(url)
        print("Download: ",url)
        try:
            html = urllib2.urlopen(url).read()
        except urllib2.URLError as e:
            print("Download error: ",e.reason)
            html = None
        return html

    现在,当出现下载错误时,该函数能够捕获到异常,然后返回None。

    重新下载

      下载时遇到的错误经常是临时性的,比如服务器过载时返回的 503 service unavailable 错误。对于此类错误,我们可以尝试重新下载,因为这个服务器问题现在可能已解决。不过,我们不需要对所有错误都尝试重新下载。如果服务器返回的是 404 not found 这种错误,则说明该网页目前并不存在,再次尝试同样的请求一般也不会出现不同的结果。

      互联网工程任务组(Inter Engineering Task Force)定义了HTTP错误的完整列表,详情可参考 http://tools.ietf.org/html/rfc7231#section-6  从该文档中,我们可以了解到 4XX 错误发生在请求存在问题时,而 5XX 错误发生在服务端存在问题时。所以,我们只需要确保 download 函数在发生 5XX 错误时重试下载即可。下面是支持重试下载功能的新版本代码。

    #python2
    import urllib2
    
    def download(url, num_retries=2):
        print 'Download:',url
        try:
            html = urllib2.urlopen(url).read()
        except urllib2.URLError as e:
            print('Download error: ',e.reason)
            html = None
            if num_retries > 0:
                if hasattr(e, 'code') and 500 <= e.code <600:    #hasattr() 函数用于判断对象是否包含对应的属性。
                    # recursively retry 5xx HTTP errors
                    return download(url, num_retries-1)
        return html


    #maybe made in Richard lawson
    #python3
    import os
    import urllib.request
    import urllib.error
    
    def download(url, num_retries=2):
        print ("Download:",url)
        try:
            html = urllib.request.urlopen(url).read()
        except urllib.error.URLError as e:
            print("Download error: ",e.reason)
            html = None
            if num_retries > 0 and 500 <= e.code <600:
                # recursively retry 5xx HTTP errors
                return download(url, num_retries-1)
        return html
    
        
    
    
    print(download("http://httpstat.us/500"))
    
    os.system("pause")
    #made in China

    现在,当download函数遇到 5XX 错误码时,将会递归调用函数自身进行尝试。此外,该函数还增加了一个参数,用于设定重试下载的次数,其默认值为两次。我们在这里限制网页下载的尝试次数,是因为服务器错误可能暂时还没有解决。想要测试该函数,可以尝试下载 http://httpstat.us/500 ,该网站会始终返回500错误码。

    将会显示类似如下的文本

    Download: http://httpstat.us/500
    Download error:  Internal Server Error
    Download: http://httpstat.us/500
    Download error:  Internal Server Error
    Download: http://httpstat.us/500
    Download error:  Internal Server Error
    None
    请按任意键继续. . .

    从上面的返回结果可以看出,download 函数的行为和预期一致,先尝试下载网页,在接收到500错误后,又进行了两次重试才放弃。

    设置用户代理

      默认情况下,urllib2 使用Python-urllib/2.7 作为用户代理下载网页内容,其中2.7是Python的版本号。如果能使用可辨识的用户代理则更好,这样可以避免我们的网络爬虫碰到一些问题。此外,也许是因为曾经经历过质量不佳的Python网络爬虫造成的服务器过载,一些网站还会封禁这个默认的用户代理。比如,在使用python默认用户代理的情况下,访问 http://meetup.com/ ,目前会返回如下访问拒绝提示。

    Access denied
    
    The owner of this website(www.meetup.com) has banned your access based on your brower's signature (1754134676cf0ac4-ua48).
    
    Ray ID: 1754134676cf0ac4
    Timestamp:Mon,06-Oct-14 18:55:48 GMT
    Your IP address:
    Requested URL:www.meetup.com/
    Error reference number: 1010
    Server ID: FL_33F7
    User-Agent: Python-urllib/2.7

      因此,为了下载更加可靠,我们需要控制用户代理的设定。下面的代码对 download 函数进行了修改,设定了一个默认的用户代理“wswp”(即web scraping with python 的首字母缩写)。

    def download(url, user_agent='wswp', num_retries=2):
        print 'Download:', url 
        headers = {'User-agent':user_agent}
        request = urllib2.Request{url, headers=headers}
        try:
            html = urllib2.urlopen(request).read()
        except urllib.URLError as e:
            print 'Download error:', e.reason
            html = None
            if num_retries > 0:
                if hasattr(e, 'code') and 500 <= e.code <600:
                # recursively retry 5xx HTTP errors
                return download(url, num_retries-1)
        return html

    现在,我们拥有了一个灵活的下载函数,可以在后续示例中得到复用。该函数能够捕获异常、重试下载并设置用户代理。

  • 相关阅读:
    测试精进之路
    访问Apache服务器自动跳转到https协议
    如何安装Chrome OS系统
    遇到Project Target Framework Not Installed解决方法
    2019开发者调查结果和总结
    「工具神器」推荐一个扒网页的神器
    Linux 使用Unzip提示write error (disk full?). Continue? (y/n/^C)的解决方法
    安卓编译Failed to authenticate Jack server certificate错误问题解决办法
    如何手动给APK文件签名
    如何给个人网站添加免费的SSL
  • 原文地址:https://www.cnblogs.com/callmebg/p/9324303.html
Copyright © 2020-2023  润新知