Crawler——链接爬虫

对数据的提取和收集也是数据分析中一大重点,所以,学习爬虫是非常有用的。完成数据采集,对后面的数据分析做下基础。

今天,要介绍的是来自《Web Scraping With Python》中的一个示例——链接爬虫。对于此类进行了简单的总结,便于相互学习。

#! /usr/bin/env python
# -*- coding:utf-8 -*-
import re
import urlparse
import urllib2
import time
from datetime import datetime
import robotparser
import Queue
# 链接爬虫
‘‘‘
一个链接爬虫需要考虑以下几个问题:
1.下载网页时,我们可能会遇到不可控制的错误,比如请求的网页可能不存在。就要用到try和except语句,捕获异常。
2.下载网页时,我们也可能会遇上临时性的错误,比如服务器过载返回的503 Service Unavailable错误。就要多尝试几次下载。
3.一些网站可能会封杀默认的用户代理,所以,我们应该重新设置一个用户代理user_agent=‘wswp‘。
4.下载网站链接时,应当考虑符合自己目标的链接,筛选出自己感谢的东西。通常用正则表达式来匹配这些链接。‘<a[^>]+href=["\‘](.*?)["\‘]‘.
5.应当考虑网页中的链接是什么链接,如果是绝对链接就没事,如果是相对链接就应该创建绝对链接。urlparse.urljoin()
6.爬取网页的时候,经常会出现将要爬取的网页中也有爬取过的链接,这样会造成不断循环。所以要建立一个URL管理器,管理爬取过的和未爬取的
7.所有爬虫都应当遵守爬虫协议(robots.txt),所以要引入robotparser模块,以避免下载禁止爬取的URL
8.有时我们需要使用代理访问某个网站。
9.如果我们爬取网站的速度过快,就会面临被封禁或者服务器过载的风险。所以应当在两次下载之间添加延时。delay
10.有些网站中含有动态内容,如果爬取该网页就会出现无限制的网页,所以为了避免爬虫陷阱,最好设置一个爬取深度(max_depth)——记录到达当前网页经过了多少链接。
‘‘‘
def link_crawler(seed_url, link_regex=None, delay=5, max_depth=-1, max_urls=-1, headers=None, user_agent=‘wswp‘, proxy=None, num_retries=1):
    """Crawl from the given seed URL following links matched by link_regex
    """
    # the queue of URL‘s that still need to be crawled
    crawl_queue = Queue.deque([seed_url])
    # the URL‘s that have been seen and at what depth
    seen = {seed_url: 0}
    # track how many URL‘s have been downloaded
    num_urls = 0
    rp = get_robots(seed_url)
    throttle = Throttle(delay)
    headers = headers or {}
    if user_agent:
        headers[‘User-agent‘] = user_agent

    while crawl_queue:
        url = crawl_queue.pop()
        # check url passes robots.txt restrictions
        if rp.can_fetch(user_agent, url):
            throttle.wait(url)
            html = download(url, headers, proxy=proxy, num_retries=num_retries)
            links = []

            depth = seen[url]
            if depth != max_depth:
                # can still crawl further
                if link_regex:
                    # filter for links matching our regular expression
                    for link in get_links(html):
                        if re.match(link_regex, link):
                            links.extend(link)
                    # links.extend(link for link in get_links(html) if re.match(link_regex, link))

                for link in links:
                    link = normalize(seed_url, link)
                    # check whether already crawled this link
                    if link not in seen:
                        seen[link] = depth + 1
                        # check link is within same domain
                        if same_domain(seed_url, link):
                            # success! add this new link to queue
                            crawl_queue.append(link)

            # check whether have reached downloaded maximum
            num_urls += 1
            if num_urls == max_urls:
                break
        else:
            print ‘Blocked by robots.txt:‘, url

class Throttle:
    """Throttle downloading by sleeping between requests to same domain
    """
    def __init__(self, delay):
        # amount of delay between downloads for each domain
        self.delay = delay
        # timestamp of when a domain was last accessed
        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, headers, proxy, num_retries, data=None):
    print ‘Downloading:‘, url
    request = urllib2.Request(url, data, headers)
    opener = urllib2.build_opener()
    if proxy:
        proxy_params = {urlparse.urlparse(url).scheme: proxy}
        opener.add_handler(urllib2.ProxyHandler(proxy_params))
    try:
        response = opener.open(request)
        html = response.read()
        code = response.code
    except urllib2.URLError as e:
        print ‘Download error:‘, e.reason
        html = ‘‘
        if hasattr(e, ‘code‘):
            code = e.code
            if num_retries > 0 and 500 <= code < 600:
                # retry 5XX HTTP errors
                return download(url, headers, proxy, num_retries-1, data)
        else:
            code = None
    return html

def normalize(seed_url, link):
    """Normalize this URL by removing hash and adding domain
    """
    link, _ = urlparse.urldefrag(link) # remove hash to avoid duplicates
    return urlparse.urljoin(seed_url, link)

def same_domain(url1, url2):
    """Return True if both URL‘s belong to same domain
    """
    return urlparse.urlparse(url1).netloc == urlparse.urlparse(url2).netloc

def get_robots(url):
    """Initialize robots parser for this domain
    """
    rp = robotparser.RobotFileParser()
    rp.set_url(urlparse.urljoin(url, ‘/robots.txt‘))
    rp.read()
    return rp

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)

if __name__ == ‘__main__‘:
    link_crawler(‘http://example.webscraping.com‘, ‘/(index|view)‘, delay=0, num_retries=1, user_agent=‘BadCrawler‘)
    link_crawler(‘http://example.webscraping.com‘, ‘/(index|view)‘, delay=0, num_retries=1, max_depth=-1, user_agent=‘GoodCrawler‘)

  

时间: 2025-01-11 10:40:39

Crawler——链接爬虫的相关文章

[CareerCup] 10.5 Web Crawler 网络爬虫

10.5 If you were designing a web crawler, how would you avoid getting into infinite loops? 这道题问如果让我们设计一个网络爬虫,怎么样才能避免进入无限循环.那么何谓无限循环呢,如果我们将网络看做一个图Graph,无限循环就是当存在环Circle时可能发生的情况.当我们用BFS来进行搜索时,每当我们访问过一个网站,我们将其标记为已访问过,下次再遇到直接跳过.那么如何定义访问过呢,是根据其内容还是根据其URL链

33款可用来抓数据的开源爬虫软件工具

要玩大数据,没有数据怎么玩?这里推荐一些33款开源爬虫软件给大家. 爬虫,即网络爬虫,是一种自动获取网页内容的程序.是搜索引擎的重要组成部分,因此搜索引擎优化很大程度上就是针对爬虫而做出的优化. 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成.传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件.聚焦爬虫的工作流程较为复杂,需要根据一定的网页分析算法过滤与主

开源爬虫汇总表,83款 网络爬虫开源软件

世界上已经成型的爬虫软件多达上百种,本文对较为知名及常见的开源爬虫软件进行梳理,按开发语言进行汇总,如下表所示.虽然搜索引擎也有爬虫,但本次我汇总的只是爬虫软件,而非大型.复杂的搜索引擎,因为很多兄弟只是想爬取数据,而非运营一个搜索引擎. 开源爬虫汇总表 开发语言 软件名称 软件介绍 许可证 Java Arachnid 微型爬虫框架,含有一个小型HTML解析器 GPL crawlzilla 安装简易,拥有中文分词功能 Apache2 Ex-Crawler 由守护进程执行,使用数据库存储网页信息

一个js爬虫

1. 第一个demo 2. configs详解——之成员 3. configs详解——之field 4. configs详解——之site, page和console 5. configs详解——之回调函数 6. 爬虫进阶开发——之内置函数 7. 爬虫进阶开发——之模板化 8. 爬虫进阶开发——之图片云托管 9. 爬虫进阶开发——之自动IP代理 10. 爬虫进阶开发——之验证码识别 11. 爬虫进阶开发——之自动JS渲染 12. 爬虫进阶开发——之技巧篇 13. 两个完整demo 14. 开发神

爬虫_Crawler4j的使用

Crawler4j的使用 (以下内容全部为转载,供自己查阅用) 下载地址: http://code.google.com/p/crawler4j/ Crawler4j的使用 网上对于crawler4j这个爬虫的使用的文章很少,Google到的几乎没有,只能自己根据crawler4j的源码进行修改.这个爬虫最大的特点就是简单易用,他连API都不提供.刚开始的时候实在恨不能适应.好在他的源码也提供了几个例子.对于一般的应用大可以直接修改它的例子. 使用方法很简单,直接用Eclipse打开工程.可以看

主流开发语言 33 款开源爬虫

原文地址 去年,之前的同事,喜欢看小说,就想自己没事搞个网站,我告诉他,先用爬虫把别人网站的小说下载下来,放到自己的网站里~我同事编码能力很强,学东西相当快,给他大概讲一下,帮他下载个用 http 协议下载网站的程序集(.net)就可以,但是,时不时,Web 会拒绝,后来,我说,http 协议是应用层协议,频繁访问人家 Web,可能会封你的 IP,你要写爬虫,可以干脆用 TCP/IP 网络层协议写~后来,他写熟了,直接用 TCP/IP 协议写的~ 现在想想,爬虫,这么多开源项目,自己写还真是多余

爬虫_83款 网络爬虫开源软件

1.http://www.oschina.net/project/tag/64/spider?lang=0&os=0&sort=view& 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. 尽管Web搜索是漫游Internet的基本要求, 但是现有web搜索引擎的数目却在下降. 并且这很有可能进一步演变成为一个公司垄断了几乎所有的web... 更多Nutch信息 最近更新:[每日一博]Nu

83款 网络爬虫开源软件

1.http://www.oschina.net/project/tag/64/spider?lang=0&os=0&sort=view& 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. 尽管Web搜索是漫游Internet的基本要求, 但是现有web搜索引擎的数目却在下降. 并且这很有可能进一步演变成为一个公司垄断了几乎所有的web... 更多Nutch信息 最近更新:[每日一博]Nu

爬虫介绍02:爬取第一个站点

为了搜刮某个站点,第一步我们需要下载该站包含有用信息的页面,也就是我么尝尝提到的爬取过程.爬站的方式多种多样,我们需要根据目标站点的结构选择合适的爬站方案.下面讨论如何安全的爬站,以及常用的三种方法: Crawling a sitemap Iterating the database IDs of each web page Following web page links 1. 下载一个Web页面 爬取网页前,首先需要下载他们.下面的Python脚本,使用了Python的 urllib2 模块