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(']+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源代码

最后

  • 项目的代码的github地址webrobot
  • 有什么问题加微博讨论van1988ch

你可能感兴趣的:(python爬虫系列-3)