python爬虫系列-3

image

1.系列文章列表

python爬虫系列-1
python爬虫系列-2

源码

#!/usr/bin/env python
# -*- coding: utf8 -*-

__author__ = 'van1988ch'

import urllib2
import re
import urlparse
from datetime import datetime
import time

class Throttle:
    """限速,每个域名一个计时器
    """
    def __init__(self, delay):
        self.delay = delay
        self.domains = {}
        
    def wait(self, url):
        domain = urlparse.urlparse(url).netloc
        last_accessed = self.domains.get(domain)

        if self.delay > 0 and last_accessed is not None:
            sleep_secs = self.delay - (datetime.now() - last_accessed).seconds
            if sleep_secs > 0:
                time.sleep(sleep_secs)
        self.domains[domain] = datetime.now()


def Download(url, retrynum=2):
    """抓取网页, retrynum=[500,600)错误重试次数"""
    print 'Downloading:', url
    try:
        html = urllib2.urlopen(url).read()
    except urllib2.URLError as e:
        print 'Download error:', e.reason
        html = None
        if retrynum > 0:
            if hasattr(e, 'code') and 500 <= e.code < 600:
                html = Download(url, retrynum-1)
    except :
        html = None
    return html

def link_crawler(seed_url):
    """分析网页中的内部链接来抓取全部网页
    """
    crawl_queue = [seed_url] 
    seen = set(crawl_queue)
    throttle = Throttle(3)
    while crawl_queue:
        url = crawl_queue.pop()
        throttle.wait(url)
        html = Download(url)
        if html:
            for link in get_links(html):
                link = urlparse.urljoin(seed_url, link)
                if link not in seen:
                    seen.add(link)
                    crawl_queue.append(link)


def get_links(html):
    """正则匹配分析出所有的链接
    """
    webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE)
    return webpage_regex.findall(html)

if __name__ == '__main__':
    link_crawler('http://www.iplaysoft.com/')

本篇是第三篇文章解决上篇文章的三个问题.

  • 1.没有区分相对路径和绝对路径
  • 2.由于计算机请求太快没有做限速处理,很容易被目标主机给屏蔽掉
  • 3.没有对于同一个连接去重

没有区分相对路径和绝对路径问题

这个问题可以使用python的urlparse这个库来解决,他可以根据我们的参数来决定最终的url.

>>> link = urlparse.urljoin("http://www.baidu.com", "/a")
>>> print link
http://www.baidu.com/a
>>> link = urlparse.urljoin("http://www.baidu.com", "http://www.tytt/a")
>>> print link
http://www.tytt/a

由于计算机请求太快没有做限速处理,很容易被目标主机给屏蔽掉

这个问题是通过Throttle类来处理的.根据每个域名增加一个计时器来决定是否要延迟本次请求.具体看源代码

没有对于同一个连接去重

去重问题就直接交给set来处理的.这样处理暂时来看没什么问题,但是其实还是有点粗糙.后面还会介绍基于数据库mongodb来处理去重问题.

2.总结

这个是一个爬虫的系列文章,这篇文章只是一个最简单的爬虫的代码,我们会采取由浅到深的这个一个方式来写这个系列,希望大家多多关注.github源代码

最后

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,513评论 25 709
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,422评论 19 139
  • “来不及了,来不及了。我要去做其他的事,这事就算了吧,反正下次做也行……”。 知道吗,因为这样一次次的拖拉,不但做...
    初人未勒阅读 4,716评论 4 5
  • 小狐狸近些时日很反常。 白天哈欠连天,陪兔子玩时也总提不起精神。晚上更是不好好在洞里呆着,兔子连着几晚去找他,都没...
    暗呓a阅读 1,683评论 2 1
  • #高山流水#不似十面埋伏的张力和爆发力,却有它的独特之处,关键在于每个转音都丝丝入扣,流入人心,起转回合都在娓娓道...
    Audrey_LL阅读 1,696评论 0 1