简单的爬虫网页下载举例

下载网页 (重传)

     重传功能:如果返回如503等错误吗,可以尝试重传,错误吗可以参考:https://tools.ietf.org/html/rfc7231

import urllib2

def download(url, num_retries=2):
    print 'Downloading:',url
    try:
        html = urllib2.urlopen(url).read()
    except urllib2.URLError as e:
        print 'Download error:', e.reason
        html = None
        
        # 此部分实现当返回错误为5xx时,进行重传
        if num_retries > 0:
            if hasattr(e, 'code') and 500 <= e.code < 600:
                return download(url, num_retries-1)
        # ——重传功能结束
        
        
    return html

# 测试:这个网站始终会返回 500 错误吗
download('http://httpstat.us/500')
运行结果:

设置用户代理

    缺省情况下,urllib2使用 Python-urllib/2.7 作为用户代理下载网页内容,但有些网站会封禁这个用户代理,如 http://www.meetup.com/
    因此,我们需要控制用户代理的设定,例如下面设定默认的用户代理“wswp”。

def download_c(url, user_agent='wswp', num_retries=2):
    print 'Downloading:',url
    # 设置http报文头中的代理字段
    headers = {'User-agent': user_agent}
    request = urllib2.Request(url, headers=headers)
    try:
        html = urllib2.urlopen(request).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:
                return download (url, user_agent, num_retries-1)
    return html

download_c('http://www.meetup.com')

ID遍历爬虫

    如下面这个网站URL “http://example.webscraping.com/view/Afghanistan-1”  一般情况下,Web服务器会忽略最后的这个 Afghanistan-1 字符串,只是用后面-1 的 1 这个ID来匹配对应页面,例如访问 http://example.webscraping.com/view/1 仍然可以访问同一个页面。
    因此在一些网站,我们可以忽略最后一个字段中的别名,只遍历ID来下载所有页面。

import itertools

max_errors = 5   # 设置最大错误数
num_errors = 0   # 初始错误数

# itertools.count(start, step) 无限迭代器   从start数值开始,默认为1,以step为步长无限迭代下去,直到break
for page in itertools.count(1):
    url = 'http://example.webscraping.com/view/%d' % page
    html = download(url)
    
    if html is None:
        # 错误次数加一
        num_errors += 1
        if num_errors == max_errors:
            break
    else:
        num_errors = 0
           


链接爬虫

    让爬虫跟踪页面中的链接,来访问对应页面。

# 调用正则能模块 “re”
import re

# urlparse   该模块将“相对链接”转换为”绝对链接“
import urlparse

# seed_url  种子网址          link_regex:跟踪链接的正则能表达时
def link_crawler (seed_url, link_regex):  
    cral_queue = [seed_url]        # 中括号代表由 seed_url 构成的 list 数据类型
    
    # 跟踪之前访问过的网址 (keep track which URL's have s
    een before)
    seen = set(cral_queue)   # 把访问链接 放入 seen 这个集合中     set()函数  添加到集合
    
    while cral_queue:
        url = cral_queue.pop()   # pop()方法从列表移除并返回最后一个对象或obj。
        html = download(url)
        # 提取页面中的所有链接
        for link in get_links(html):
            # 检查是否匹配跟踪链接的正则能表达时
            # re.match 从第一个字符开始匹配,如果不是起始位置匹配成功,match就返回none
            if re.match(link_regex, link):
               # urlparse.urljoin 把相对链接转换为绝对链接
               # 例如 urljoin("http://www.google.com/1/a.html", "b.html") 得到http://www.google.com/1/b.html
                link = urlparse.urljoin(seed_url, link)
               # 检查之前是否访问过该链接    在set集合 seen 中查找
                if link not in seen:
                    seen.add(link)          # set.add   在集合中添加新的对象
                    # 在队列中列表list中加入这个链接
                    crawl_queue.append(link)   # list.append   在列表末尾添加新的对象
        
# 返回 html 中的链接 list
def get_links(html):
    # 一个正则能表达式来提取网页中的所有链接
    # re.compile函数根据一个模式字符串的可选的标志参数生成一个正则能表达式对象,再通过findall返回所有匹配结果列表list。
    webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE)
        # re.IGNORECASE 忽略大小写
        #匹配例如 <a1 href= "link.html"   匹配链接的格式
    # 列出 webpage 中所有的链接       
    return webpage_regex.findall(html)  # findall   返回的是一个列表  里面是所有的链接
正则能表达式:
    
    '<a[^>]+href=["\'](.*?)["\']'
    [] 表示匹配其中任意字符
    ^> 表示除了 > 的字符
    ['\"] 表示 ‘ \ "  这三个字符中出现其中的任意一个
    (.*?)中:    . 可以匹配除 \n 外的任意字符
                * 表示前面字符任意多个
                ? 匹配前面的子表达时0次或者1次


解析 robots.txt

    robots.txt这个文件是让爬取者了解爬取该网站是存在的限制。   协议信息:http://www.robotstxt.org
    Python自带的robotparser可以解析robot文件。

import robotparser
rp = robotparser.RobotFileParser()
rp.set_url('http://example.webscraping.com/robots.txt')
rp.read()
url = 'http://example.webscraping.com'
user_agent = 'BadCrawler'
rp.can_fetch(user_agent, url)

爬虫最大深度

    深度——当前网页经过了多少个链接      当达到最大深度时,爬虫就不再向队列中添加该网页中的链接了。  
    要实现这个功能,需要修改seen变量,该变量原先只记录访问过的网页链接,现在修改为一个字典,增加了页面深度的记录。

def link_crawler_d(...,depth=2):
    max_depth = 2
    seen = {}
    ...
    depth = seen[url]  #获取seen字典序中 url 所对应的深度值
    if depth != max_depth:
        for link in links:
            if link not in seen:
                seen[link] = depth+1
                crawl_queue.append(link)
                


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值