爬虫与限流器

# 爬虫我们为了做的像浏览器就需要限流器来伪装,也就是将在时间上做文章

 1 import urllib.request as ure
 2 import re
 3 import urllib.parse
 4 from delayed import Throttle
 5 #下载网页并返回HTML(动态加载的部分下载不了)
 6 def download(url,user_agent='Socrates',num=2):
 7     print('下载:'+url)
 8     #设置用户代理
 9     headers = {'user_agent':user_agent}
10     request = ure.Request(url,headers=headers)
11     try:
12         #下载网页
13         html = ure.urlopen(request).read()
14     except ure.URLError as e:
15         print('下载失败'+e.reason)
16         html=None
17         if num>0:
18             #遇到5XX错误时,递归调用自身重试下载,最多重复2次
19             if hasattr(e,'code') and 500<=e.code<600:
20                 return download(url,num-1)
21     return html
22 #seed_url传入一个url
23 #link_regex传入一个正则表达式
24 #函数功能:提取和link_regex匹配的所有网页链接并下载
25 def link_crawler(seed_url, link_regex):
26     html = download(seed_url)
27     crawl_queue = []
28     #迭代get_links()返回的列表,将匹配正则表达式link_regex的链接添加到列表中
29     for link in get_links(html):
30         if re.match(link_regex, link):
31             #拼接https://www.cnblogs.com/ 和 /cate/...
32             link = urllib.parse.urljoin(seed_url, link)
33             #不在列表中才添加
34             if link not in crawl_queue:
35                 crawl_queue.append(link)
36     #调用WaitFor的wait()函数,下载限速,间隔小于2秒则等待,直到时间等于2秒才继续下载(大于则直接继续下载)
37     throttle = Throttle(2)
38     #下载crawl_queue中的所有网页
39     while crawl_queue:
40         #删除列表末尾的数据
41         url = crawl_queue.pop()
42         throttle.wait(url)
43         download(url)
44 #传入html对象,以列表形式返回所有链接
45 def get_links(html):
46     #使用正则表达式提取html中所有网页链接
47     webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']',re.IGNORECASE)
48     html = html.decode('utf-8')
49     # 以列表形式返回所有网页链接
50     return webpage_regex.findall(html)
51 
52 link_crawler('http://www.runoob.com/','/python3/.*')


(二)delayed.py(实现下载限速的类)

import urllib.parse
import datetime
import time
class Throttle:
    def __init__(self,delay):
        # delay:希望延迟多长时间(wait()中的处理是以秒为单位)
        self.delay = delay
        #用来存放上次下载时间
        self.domains = dict()

    def wait(self,url):
        # 获取url netloc属性的值(即www.cnblogs.com,// 和第一个 /之间的内容)
        domain = urllib.parse.urlparse(url).netloc
        # 存在键值为domain的数据返回value值,否则返回None
        last_down = self.domains.get(domain)
        if self.delay >0 and last_down is not None:
            # 希望延迟时间 - (当前时间-上次下载时间),seconds时间间隔以秒为单位显示
            sleep_sec = self.delay-(datetime.datetime.now()-last_down).seconds
            if sleep_sec > 0:
                time.sleep(sleep_sec)
        #将当前时间添加到domains中
        self.domains[domain] = datetime.datetime.now()

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值