文章目录

一、爬虫概念1.1、增量式爬虫1.2、深层爬虫

二、增量式爬虫的实现步骤三、增量式爬虫案例

今天在这里分享一些关于爬虫技术的介绍,主要以增量式爬虫介绍为主。

一、爬虫概念

所谓爬虫,其本质是一种计算机程序,它的行为看起来就像是蜘蛛在网上面爬行一样,顺着互联网这个“网”,一条线一条线地“爬行”。所以爬虫在英文中又叫作“Spider”,正是蜘蛛这个单词。 爬虫的主要目的是获取网页内容并解析。 在互联网发展的势头下,各种开发技术变得日新月异,面对不同场景的需求衍生了类型众多的网络爬虫。网络爬虫按照系统结构和实现技术大致可以分为4种类型,分别是通用网络爬虫、聚焦网络爬虫、增量式网络爬虫(广度优先)、深层网络爬虫(深度优先)。

有关其它爬虫技术,请参考:【由浅入深】爬虫技术,值得收藏,来了解一下~

1.1、增量式爬虫

增量式网终爬虫(Incremental Web Crawler)是指对已下载的网页采取增量式更新,只抓取新产生或者已经发生变化的网页的网络爬虫。 增量式网络爬虫只会抓取新产生的或内容变化的网页,并不会重新抓取内容未发生变化的网页,这样可以有效地减少网页的下载量,减少访问时间和存储空间的耗费,但是增加了网页抓取算法的复杂度和实现难度。

1.2、深层爬虫

深层网络爬虫(Deep Web Crawler)是指抓取深层网顷的网络爬虫,它要抓取的网页层次比较深,需要通过一定的附加策略才能够自动抓取,实现难度较大。

二、增量式爬虫的实现步骤

编写增量爬虫的一般步骤如下:

定义一个数据存储结构,记录已经爬取过的网页和相关信息,比如最后访问时间、页面内容哈希等。可以使用数据库或文件系统等方式进行存储。 确定需要爬取的网站,设计好爬虫的起始点。 从起始点开始爬取页面,并从页面中提取需要的信息。 对提取到的信息进行处理和存储,同时更新已经爬取过的页面的相关信息。 针对更新过的页面和可能的新页面,重复以上步骤,直到完成所有的爬取任务。 可以添加一些限制条件,比如爬取深度、爬取速度等,以避免给目标网站造成过大的负担。

需要注意的是,增量爬虫需要针对已经爬取过的页面进行更新和去重,可以根据页面的哈希值或者其他唯一标识进行比较和判断。同时,增量爬虫可能需要处理一些更新频率较高的页面,需要根据实际情况进行设计和优化。

三、增量式爬虫案例

下面是一个简单的增量式爬虫案例,用于从某个新闻网站抓取新闻文章的标题和链接,并实现增量爬取功能:

import requests

import hashlib

import time

import pymysql

from bs4 import BeautifulSoup

# 定义爬虫起始点和目标站点

start_url = 'https://news.example.com'

target_site = 'example.com'

# 定义数据库连接和数据表结构

conn = pymysql.connect(host='localhost', user='root', password='password', database='news_db', charset='utf8mb4')

cursor = conn.cursor()

cursor.execute('''

CREATE TABLE IF NOT EXISTS news (

id INT PRIMARY KEY AUTO_INCREMENT,

title TEXT,

url TEXT,

hash TEXT,

last_modified BIGINT

)

''')

# 定义页面哈希函数

def get_hash(url, content):

return hashlib.sha1(f'{url}{content}'.encode('utf-8')).hexdigest()

# 定义页面访问函数

def fetch_page(url):

response = requests.get(url)

if response.status_code == 200:

return response.text

else:

return None

# 定义页面解析函数

def parse_page(content):

soup = BeautifulSoup(content, 'html.parser')

news_list = soup.find_all('a', {'class': 'news-link'})

for news in news_list:

title = news.text.strip()

url = news['href'].strip()

yield (title, url)

# 定义增量爬取函数

def crawl_incremental():

last_modified = None

cursor.execute('SELECT MAX(last_modified) FROM news')

row = cursor.fetchone()

if row[0]:

last_modified = row[0]

current_url = start_url

while True:

content = fetch_page(current_url)

if content is None:

break

hash_value = get_hash(current_url, content)

if hash_value in visited_urls:

break

visited_urls.add(hash_value)

for title, url in parse_page(content):

if target_site in url:

cursor.execute('SELECT * FROM news WHERE url = %s', (url,))

row = cursor.fetchone()

if row:

# 已经爬取过该页面,检查是否需要更新

if row[4] < last_modified:

# 页面已经更新,重新爬取

cursor.execute('DELETE FROM news WHERE url = %s', (url,))

conn.commit()

crawl_url(url)

else:

# 页面没有更新,跳过

pass

else:

# 第一次爬取该页面

cursor.execute('INSERT INTO news (title, url, hash, last_modified) VALUES (%s, %s, %s, %s)',

(title, url, get_hash(url, fetch_page(url)), int(time.time())))

conn.commit()

current_url = get_next_url(content)

# 定义获取下一个页面链接的函数

def get_next_url(content):

# 略去具体实现

pass

# 开始爬取

visited_urls = set()

crawl_incremental()

# 关闭数据库连接

conn.close()

具体来说,增量爬取函数crawl_incremental()中,我们通过查询数据库中已有的新闻页面的最后修改时间,以及使用SELECT语句检查数据库中是否已有某个页面的记录,来实现增量爬取。如果数据库中已有该页面的记录,就检查该页面的最后修改时间,如果该时间早于已有的最后修改时间,则说明页面已经更新,需要重新爬取,否则跳过。如果数据库中没有该页面的记录,则说明该页面是新页面,需要将其插入到数据库中。

需要注意的是,MySQL数据库的操作需要建立连接、打开游标、提交事务等步骤,因此需要在合适的地方进行相关操作,确保数据能够正确地插入或删除。另外,MySQL数据库需要指定字符集,以支持中文等非ASCII字符的存储和查询,因此需要在连接数据库时指定字符集为utf8mb4。

综上所述,以上是一个使用MySQL数据库实现增量爬虫的示例代码。实际应用中,需要根据具体的爬取需求和数据存储方式进行相应的修改和优化。

注意: yield是Python中的关键字,用于生成器函数中的语句。当函数执行到yield语句时,会返回一个值,并暂停函数的执行,等待下一次调用时继续执行。因此,生成器函数可以返回多个值,并且每次返回一个值时可以暂停函数的执行,避免一次性生成所有值所带来的性能问题。

在上面的代码中,parse_page函数是一个生成器函数,用于解析新闻网站的HTML页面,返回新闻标题和链接。当调用parse_page函数时,它并不会一次性返回所有新闻标题和链接,而是通过yield关键字逐个返回。具体来说,parse_page函数会首先使用BeautifulSoup库解析HTML页面,然后通过find_all方法找到所有元素,再逐个提取元素的text和href属性作为新闻标题和链接,并通过yield关键字逐个返回。在爬虫函数中,可以通过for … in …循环逐个遍历parse_page函数的返回值,获得每个新闻的标题和链接,并进行后续的处理。

总之,yield关键字是生成器函数中的重要语句,它可以使函数的返回值逐个生成并返回,避免一次性生成所有值所带来的性能问题,也方便进行迭代处理

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: