待抓取URL队列
在爬虫系统中,待抓取的URL队列至关重要。这相当于一份待办事项列表,它指引着爬虫应访问哪些网页。队列中URL的排列顺序,直接影响到抓取的顺序。比如,是先抓取热门新闻网站,还是先探索小众论坛,顺序的不同,会带来效率和结果的差异。合理的排序有助于爬虫更高效地运行。
确定URL的排列时,需考虑爬取目标和策略。若目标是迅速获取大量信息,优先选择数据丰富的大网站是明智之举。举例来说,若要收集商品信息,应先从大型电商平台入手,这样可以较快地获取更多数据。而若目的是探索未知领域,则可能需要平衡地抓取不同类型网站的URL。
实现爬虫
掌握爬虫的操作步骤和抓取技巧后,便可以开始实际操作。然而,在实际操作过程中,有许多细节需要注意。如果直接使用现成的代码来抓取知乎用户信息,会遇到不少困难。知乎拥有六千万每月活跃用户,数据量巨大,直接运行代码抓取信息会耗费大量时间。
import Queue
initial_page = "https://www.zhihu.com/people/gaoming623"
url_queue = Queue.Queue()
seen = set()
seen.insert(initial_page)
url_queue.put(initial_page)
while(True): #一直进行
if url_queue.size()>0:
current_url = url_queue.get() #拿出队例中第一个的 url
store(current_url) #把这个 url 代表的网页存储好
for next_url in extract_urls(current_url): #提取把这个 url 里链向的 url
if next_url not in seen:
seen.put(next_url)
url_queue.put(next_url)
else:
break
在编写爬虫程序时,需注意对代码和抓取方法进行优化,以提升工作效率。应控制每次抓取的数据量,并妥善安排请求间的间隔。同时,运用多线程和异步编程等技术,可以加速数据抓取。此外,还需针对目标网站的特性,灵活调整程序,以防被反爬虫措施所阻拦。
网页判重复杂度
全网包含N个网站,处理重复内容的难度相当关键。爬虫需确保每个页面只被抓取一次,这就要求对所有页面进行遍历以判断重复。若采用常规的集合结构,每次判断重复的复杂度为log(N),整体上则是N乘以log(N)。在处理大量数据时,这种复杂度导致效率较低。
观察实际情况,大规模的网站爬虫项目需要处理数亿网页。若采用传统方法进行重复判断,不仅会耗费大量计算资源,还会对爬虫的性能产生负面影响,进而减慢爬取速度。鉴于此,我们迫切需要寻找一种更为高效的重复判断手段。
Bloom Filter判重
# bloom_filter.py
BIT_SIZE = 5000000
class BloomFilter:
def __init__(self):
# Initialize bloom filter, set size and all bits to 0
bit_array = bitarray(BIT_SIZE)
bit_array.setall(0)
self.bit_array = bit_array
def add(self, url):
# Add a url, and set points in bitarray to 1 (Points count is equal to hash funcs count.)
# Here use 7 hash functions.
point_list = self.get_postions(url)
for b in point_list:
self.bit_array[b] = 1
def contains(self, url):
# Check if a url is in a collection
point_list = self.get_postions(url)
result = True
for b in point_list:
result = result and self.bit_array[b]
return result
![图片[2]-Python爬虫实现指南:从基本流程到抓取策略详解-东山笔记](https://83ch.com/wp-content/themes/zibll/img/thumbnail-lg.svg)
def get_postions(self, url):
# Get points positions in bit vector.
point1 = mmh3.hash(url, 41) % BIT_SIZE
point2 = mmh3.hash(url, 42) % BIT_SIZE
point3 = mmh3.hash(url, 43) % BIT_SIZE
point4 = mmh3.hash(url, 44) % BIT_SIZE
point5 = mmh3.hash(url, 45) % BIT_SIZE
point6 = mmh3.hash(url, 46) % BIT_SIZE
point7 = mmh3.hash(url, 47) % BIT_SIZE
return [point1, point2, point3, point4, point5, point6, point7]
Bloom Filter是一种高效的去重工具。本质上,它运用了哈希技术。不过,它只需固定内存空间,不会随URL数量增加而扩展。它能在极短时间内,以O(1)的效率判断URL是否已存在于集合中。这种特性显著提升了去重效率,同时节省了内存资源。对于大型爬虫项目而言,这一特性尤为实用。
Bloom Filter存在一定的限制。在判断URL是否存在于集合中时,存在2%的不确定性。换句话说,可能会出现一些误判。在那些对结果精确度要求极高的场合,需要结合其他技术来提升检测的准确性。然而,对于大多数爬虫任务来说,这样的小误差是可以容忍的。
CREATE DATABASE `zhihu_user` /*!40100 DEFAULT CHARACTER SET utf8 */;
-- User base information table
CREATE TABLE `t_user` (
`uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`brief_info` varchar(400) COMMENT '个人简介',
`industry` varchar(50) COMMENT '所处行业',
`education` varchar(50) COMMENT '毕业院校',
`major` varchar(50) COMMENT '主修专业',
`answer_count` int(10) unsigned DEFAULT 0 COMMENT '回答数',
`article_count` int(10) unsigned DEFAULT 0 COMMENT '文章数',
`ask_question_count` int(10) unsigned DEFAULT 0 COMMENT '提问数',
`collection_count` int(10) unsigned DEFAULT 0 COMMENT '收藏数',
`follower_count` int(10) unsigned DEFAULT 0 COMMENT '被关注数',
`followed_count` int(10) unsigned DEFAULT 0 COMMENT '关注数',
`follow_live_count` int(10) unsigned DEFAULT 0 COMMENT '关注直播数',
`follow_topic_count` int(10) unsigned DEFAULT 0 COMMENT '关注话题数',
`follow_column_count` int(10) unsigned DEFAULT 0 COMMENT '关注专栏数',
`follow_question_count` int(10) unsigned DEFAULT 0 COMMENT '关注问题数',
`follow_collection_count` int(10) unsigned DEFAULT 0 COMMENT '关注收藏夹数',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modify` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次编辑',
PRIMARY KEY (`uid`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户基本信息表';
用户信息存储
下载网页信息,借助XPath技术进行解析,从中提取用户的多方面数据。XPath作为一项强有力的手段,能够精确锁定网页中的元素,使我们能够轻松获取所需资料,诸如用户名、加入时间、联系方式等。这些数据被妥善存储于数据库中,便于后续的深入分析和处理。
网站用户信息的存储方式各有差异,需依据实际情况作出相应调整。通常涉及用户基础信息表格、用户行为数据表格等。在构建数据库表格结构时,需注重数据的完整性、统一性以及查询速度,确保数据得以高效存储与应用。
反爬虫与应对
网站在防范爬虫方面措施多样。它通常会检查用户的请求,比如通过识别User-Agent和Referer。许多网站会检查User-Agent,以此来区分请求是来自浏览器还是爬虫。而对于资源网站,它们会通过检测Referer来防止盗链。遇到此类机制时,我们可以在爬虫中加入请求头,模仿浏览器的User-Agent,并对Referer进行修改或添加,以此来规避检测。
网站会监控用户的活动,若同一IP在短时间内频繁访问同一页面,或同一账户在短时间内重复执行相同操作,这种情况较为常见。通常,通过使用IP代理可以解决这个问题。像爬虫技术人员那样的人,会储备许多代理IP,每次请求后更换一次,这样就能轻易绕过反爬虫机制。例如,在爬取知乎时,单个IP很快会被限制,但使用代理IP就能继续进行爬取。
cookies = {
"d_c0": "AECA7v-aPwqPTiIbemmIQ8abhJy7bdD2VgE=|1468847182",
"login": "NzM5ZDc2M2JkYzYwNDZlOGJlYWQ1YmI4OTg5NDhmMTY=|1480901173|9c296f424b32f241d1471203244eaf30729420f0",
"n_c": "1",
"q_c1": "395b12e529e541cbb400e9718395e346|1479808003000|1468847182000",
"l_cap_id": "NzI0MTQwZGY2NjQyNDQ1NThmYTY0MjJhYmU2NmExMGY=|1480901160|2e7a7faee3b3e8d0afb550e8e7b38d86c15a31bc",
"d_c0": "AECA7v-aPwqPTiIbemmIQ8abhJy7bdD2VgE=|1468847182",
"cap_id": "N2U1NmQwODQ1NjFiNGI2Yzg2YTE2NzJkOTU5N2E0NjI=|1480901160|fd59e2ed79faacc2be1010687d27dd559ec1552a"
}
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.3",
"Referer": "https://www.zhihu.com/"
}
r = requests.get(url, cookies = cookies, headers = headers)
在使用爬虫过程中,大家是否遇到过特别棘手的反爬虫策略?欢迎各位积极留言交流,同时别忘了点赞并转发这篇文章!