一、域名去重
1、检测开头:link.startswith('http')
txt = "Hello, welcome to my world."

x = txt.startswith("Hello")

print(x)
#如果字符串以指定的值开头,则 startswith() 方法返回 True,否则返回 False。

string.startswith(value, start, end)
 



2、tldextract模块准确获取域名和后缀

  tldextract是一个第三方模块,意思就是Top Level Domain extract,即顶级域名提取
  使用时 需要安装,命令如下
  pip install tldextract
  URL的结构,news.baidu.com 里面的news.baidu.com叫做host,它是注册域名baidu.com的子域名,而com就是顶级域名TLD。

  

     tld = tldextract.extract(link)
if tld.domain == 'baidu':
continue
news_links.append(link)
 参考链接:https://www.yuanrenxue.com/crawler/news-crawler.html

二、url的清洗

  1、判断网页种类(静态网页?图片?等等的内容)
  2、去除外部的链接(广告)
   
  
#Python find() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返回-1。

g_bin_postfix = set([
'exe', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
'pdf',
'jpg', 'png', 'bmp', 'jpeg', 'gif',
'zip', 'rar', 'tar', 'bz2', '7z', 'gz',
'flv', 'mp4', 'avi', 'wmv', 'mkv',
'apk',
]) g_news_postfix = [
'.html?', '.htm?', '.shtml?',
'.shtm?',
] def clean_url(url):
# 1. 是否为合法的http url
if not url.startswith('http'):
return ''
# 2. 去掉静态化url后面的参数
for np in g_news_postfix:
p = url.find(np)
if p > -1:
p = url.find('?')
url = url[:p]
return url
# 3. 不下载二进制类内容的链接
up = urlparse.urlparse(url)
path = up.path
if not path:
path = '/'
postfix = path.split('.')[-1].lower()
if postfix in g_bin_postfix:
return '' # 4. 去掉标识流量来源的参数
# badquery = ['spm', 'utm_source', 'utm_source', 'utm_medium', 'utm_campaign']
good_queries = []
for query in up.query.split('&'):
qv = query.split('=')
if qv[0].startswith('spm') or qv[0].startswith('utm_'):
continue
if len(qv) == 1:
continue
good_queries.append(query)
query = '&'.join(good_queries)
url = urlparse.urlunparse((
up.scheme,
up.netloc,
path,
up.params,
query,
'' # crawler do not care fragment
))
return url
  3、url的管理(urlpool)
  
mport pickle
import leveldb
import time
import urllib.parse as urlparse class UrlPool:
'''URL Pool for crawler to manage URLs
''' def __init__(self, pool_name):
self.name = pool_name
self.db = UrlDB(pool_name) self.waiting = {} # {host: set([urls]), } 按host分组,记录等待下载的URL
self.pending = {} # {url: pended_time, } 记录已被取出(self.pop())但还未被更新状态(正在下载)的URL
self.failure = {} # {url: times,} 记录失败的URL的次数
self.failure_threshold = 3
self.pending_threshold = 10 # pending的最大时间,过期要重新下载
self.waiting_count = 0 # self.waiting 字典里面的url的个数
self.max_hosts = ['', 0] # [host: url_count] 目前pool中url最多的host及其url数量
self.hub_pool = {} # {url: last_query_time, } 存放hub url
self.hub_refresh_span = 0
self.load_cache() def __del__(self):
self.dump_cache() def load_cache(self,):
path = self.name + '.pkl'
try:
with open(path, 'rb') as f:
self.waiting = pickle.load(f)
cc = [len(v) for k, v in self.waiting.items()]
print('saved pool loaded! urls:', sum(cc))
except:
pass def dump_cache(self):
path = self.name + '.pkl'
try:
with open(path, 'wb') as f:
pickle.dump(self.waiting, f)
print('self.waiting saved!')
except:
pass def set_hubs(self, urls, hub_refresh_span):
self.hub_refresh_span = hub_refresh_span
self.hub_pool = {}
for url in urls:
self.hub_pool[url] = 0 def set_status(self, url, status_code):
if url in self.pending:
self.pending.pop(url) if status_code == 200:
self.db.set_success(url)
return
if status_code == 404:
self.db.set_failure(url)
return
if url in self.failure:
self.failure[url] += 1
if self.failure[url] > self.failure_threshold:
self.db.set_failure(url)
self.failure.pop(url)
else:
self.add(url)
else:
self.failure[url] = 1
self.add(url) def push_to_pool(self, url):
host = urlparse.urlparse(url).netloc
if not host or '.' not in host:
print('try to push_to_pool with bad url:', url, ', len of ur:', len(url))
return False
if host in self.waiting:
if url in self.waiting[host]:
return True
self.waiting[host].add(url)
if len(self.waiting[host]) > self.max_hosts[1]:
self.max_hosts[1] = len(self.waiting[host])
self.max_hosts[0] = host
else:
self.waiting[host] = set([url])
self.waiting_count += 1
return True def add(self, url, always=False):
if always:
return self.push_to_pool(url)
pended_time = self.pending.get(url, 0)
if time.time() - pended_time < self.pending_threshold:
print('being downloading:', url)
return
if self.db.has(url):
return
if pended_time:
self.pending.pop(url)
return self.push_to_pool(url) def addmany(self, urls, always=False):
if isinstance(urls, str):
print('urls is a str !!!!', urls)
self.add(urls, always)
else:
for url in urls:
self.add(url, always) def pop(self, count, hub_percent=50):
print('\n\tmax of host:', self.max_hosts) # 取出的url有两种类型:hub=1, 普通=0
url_attr_url = 0
url_attr_hub = 1
# 1. 首先取出hub,保证获取hub里面的最新url.
hubs = {}
hub_count = count * hub_percent // 100
for hub in self.hub_pool:
span = time.time() - self.hub_pool[hub]
if span < self.hub_refresh_span:
continue
hubs[hub] = url_attr_hub # 1 means hub-url
self.hub_pool[hub] = time.time()
if len(hubs) >= hub_count:
break # 2. 再取出普通url
left_count = count - len(hubs)
urls = {}
for host in self.waiting:
if not self.waiting[host]:
continue
url = self.waiting[host].pop()
urls[url] = url_attr_url
self.pending[url] = time.time()
if self.max_hosts[0] == host:
self.max_hosts[1] -= 1
if len(urls) >= left_count:
break
self.waiting_count -= len(urls)
print('To pop:%s, hubs: %s, urls: %s, hosts:%s' % (count, len(hubs), len(urls), len(self.waiting)))
urls.update(hubs)
return urls def size(self,):
return self.waiting_count def empty(self,):
return self.waiting_count == 0

  来自猿人学官网



日爬百万数据的域名限制、url的清洗和管理的更多相关文章

  1. scrapy爬取数据的基本流程及url地址拼接

    说明:初学者,整理后方便能及时完善,冗余之处请多提建议,感谢!   了解内容: Scrapy :抓取数据的爬虫框架     异步与非阻塞的区别   异步:指的是整个过程,中间如果是非阻塞的,那就是异步 ...

  2. Python使用Scrapy框架爬取数据存入CSV文件(Python爬虫实战4)

    1. Scrapy框架 Scrapy是python下实现爬虫功能的框架,能够将数据解析.数据处理.数据存储合为一体功能的爬虫框架. 2. Scrapy安装 1. 安装依赖包 yum install g ...

  3. 阿狸V任务页面爬取数据解析

    需求: 爬取:https://v.taobao.com/v/content/video 所有主播详情页信息 首页分析 分析可以得知数据是通过ajax请求获取的. 分析请求头 详情页分析 详情页和详情页 ...

  4. web scraper——简单的爬取数据【二】

    web scraper——安装[一] 在上文中我们已经安装好了web scraper现在我们来进行简单的爬取,就来爬取百度的实时热点吧. http://top.baidu.com/buzz?b=1&a ...

  5. 关于js渲染网页时爬取数据的思路和全过程(附源码)

    于js渲染网页时爬取数据的思路 首先可以先去用requests库访问url来测试一下能不能拿到数据,如果能拿到那么就是一个普通的网页,如果出现403类的错误代码可以在requests.get()方法里 ...

  6. node.js爬取数据并定时发送HTML邮件

    node.js是前端程序员不可不学的一个框架,我们可以通过它来爬取数据.发送邮件.存取数据等等.下面我们通过koa2框架简单的只有一个小爬虫并使用定时任务来发送小邮件! 首先我们先来看一下效果图 差不 ...

  7. 【Spider】使用CrawlSpider进行爬虫时,无法爬取数据,运行后很快结束,但没有报错

    在学习<python爬虫开发与项目实践>的时候有一个关于CrawlSpider的例子,当我在运行时发现,没有爬取到任何数据,以下是我敲的源代码:import scrapyfrom UseS ...

  8. 【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜

    实验网站:虾米音乐排行榜 网站地址:http://www.xiami.com/chart  难度系数:★☆☆☆☆ 依赖库:request.lxml的etree (安装lxml:pip install ...

  9. R中使用rvest爬取数据小试

    总结R中使用 xpath 和 css selectors 获取标签内容(xpath功能强大,而CSS选择器通常语法比较简洁,运行速度更快些) 例:抓取下面标签的内容: <h3 class=&qu ...

  10. 如何分页爬取数据--beautisoup

    '''本次爬取讲历史网站'''#!usr/bin/env python#-*- coding:utf-8 _*-"""@author:Hurrican@file: 分页爬 ...

随机推荐

  1. jumpserver堡垒机版本升级,从2.14.2升级到2.16.3

    官方文档:https://docs.jumpserver.org/zh/master/install/upgrade/upgrade/ 前提说明 1.堡垒机是单节点 2.使用外置MySQL和Redis ...

  2. js内置禁用按钮 disabled

    按钮在监听到disabled后面的布尔值就可以实现是否禁用 一: <button :disabled="book.count <= 1" @click="de ...

  3. 2>&1到底是什么意思?

    java -jar snapshot.jar > snapshot.log 2>&1 & 写Java的朋友一定对上面的命令很熟悉,相信大部分人都知道>表示的是重定向, ...

  4. PAT (Basic Level) Practice 1007 素数对猜想 分数 20

    让我们定义dn​为:dn​=pn+1​−pn​,其中pi​是第i个素数.显然有d1​=1,且对于n>1有dn​是偶数."素数对猜想"认为"存在无穷多对相邻且差为2的 ...

  5. 手把手教你玩转 Gitea|使用 Docker 安装 Gitea

    使用 Docker 安装 Gitea 的过程非常简单的,堪比"一键式"安装.Gitea 安装使用系列教程将会从多种方式进行全方位的实操演示. 视频演示中使用腾讯云实验环境安装 Do ...

  6. TTD 专题 (第一篇):C# 那些短命线程都在干什么?

    一:背景 1.讲故事 在分析的众多dump中,经常会遇到各种奇葩的问题,仅通过dump这种快照形式还是有很多问题搞不定,而通过 perfview 这种粒度又太粗,很难找到问题之所在,真的很头疼,比如本 ...

  7. TomCat之安装

    TomCat 之安装(伪分布式版本) 本次安装是使用的伪分布式的安装(即一台机器安装两个tomcat) 1.通过scp导入tomcat安装包 2.解压缩成俩个文件 3.修改第一个tomcat的配置文件 ...

  8. JavaScript基础&实战 JS中正则表达式的使用

    文章目录 1.正则表达式 1.1 代码 1.2 测试结果 2.splict | search 2.1 代码 2.2 测试结果 1.正则表达式 1.1 代码 <!DOCTYPE html> ...

  9. 一篇了解全MVCC

    一.什么是MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制,是一种并发控制的方法,一般用在数据库管理系统中,实现对数据库的并发访问,比如在M ...

  10. Jquery中Trigger()方法

    1. $(selector).trigger(event,[param1,param2,...]) 方法触发被选元素标签的指定事件类型 为元素边赋值为true,并触发元素标签的change方法 $(' ...