首页 > 其他分享 >如何写一个简单的爬虫

如何写一个简单的爬虫

时间:2023-03-09 10:36:54浏览次数:24  
标签:__ links url self 爬虫 如何 depth href 简单

学习爬虫重要的是知识储备以及实战能力,最近有个学妹要求我帮她写一个爬虫程序,我将我编写的爬虫代码以及解释都记录下来,方便后期更多的伙伴们学习参考。

前置知识-爬虫定义

爬虫指的是一种自动化程序,用于在互联网上获取和抓取信息。它可以从网站中抓取数据并将其存储到本地计算机或其他数据库中,以便进一步处理和分析。

爬虫通常会自动访问网页、解析页面内容,并提取有用的信息,例如网页上的文本、图像、视频、音频、超链接等等。

requests 库:这是一个用于发送 HTTP 请求的库,可以发送 GET、POST、PUT、DELETE 等多种请求方式,并且可以设置请求头、请求体、Cookies 等信息。它还支持自动处理重定向、代理、SSL/TLS 等常见的网络请求问题,并且支持响应的解析,可以解析 JSON、HTML 等多种格式的响应数据。

urllib.parse 库:这是一个用于解析 URL 的库,它可以将 URL 拆分成各个部分,例如协议、域名、路径、查询参数等,并且可以对 URL 进行编码和解码,防止出现乱码和安全问题。

bs4 库:这是一个用于解析 HTML 和 XML 的库,可以从 HTML 或 XML 文件中提取数据,并且支持多种解析方式,例如基于标签名、CSS 选择器、正则表达式等。它还可以自动修正 HTML 或 XML 代码中的错误,方便数据提取。

正文-简单实现

首先,我们可以先实现一个简单的爬虫代码。

功能:

可以从指定的 URL 开始遍历整个网站。

输出网站中所有的链接。

关键代码实现:

import requests
from bs4 import BeautifulSoup

def crawl(url):
    # 发送 GET 请求获取页面内容
    response = requests.get(url)
    

    # 使用 BeautifulSoup 解析页面内容
    soup = BeautifulSoup(response.content, 'html.parser')


    # 获取页面中所有链接
    links = []
    for link in soup.find_all('a'):
        href = link.get('href')
        if href:
            links.append(href)


    return links

# 测试代码
if __name__ == '__main__':
    url = 'http://jshk.com.cn/mb/reg.asp?kefu=xjy'
    links = crawl(url)
    for link in links:
        print(link)

这个代码使用了python的 requests 库来发送 HTTP 请求,使用 BeautifulSoup 库来解析 HTML 页面内容,获取页面中所有链接并输出。在测试代码中,可以指定要爬取的 URL,然后输出所有链接。

第一次优化

import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin

def get_links(url):
    # 发送 GET 请求获取页面内容
    response = requests.get(url)


    # 使用 BeautifulSoup 解析页面内容
    soup = BeautifulSoup(response.content, 'html.parser')


    # 获取页面中所有链接
    links = []
    for link in soup.find_all('a'):
        href = link.get('href')
        if href:
            href = urljoin(url, href)  # 处理相对链接
            parsed_href = urlparse(href)
            if parsed_href.scheme in ('http', 'https') and parsed_href.netloc:  # 只处理 http 和 https 协议的链接
                links.append(href)


    return links

def crawl(url, max_depth=3):
    visited = set()  # 已访问过的链接
    queue = [(url, 0)]  # 待访问的链接队列
    

    while queue:
        url, depth = queue.pop(0)
        if depth > max_depth:  # 超过最大深度,停止访问
            break
 

        if url not in visited:
            visited.add(url)
            print(' ' * depth, url)
            links = get_links(url)
            for link in links:
                if link not in visited:
                    queue.append((link, depth+1))
             

# 测试代码
if __name__ == '__main__':
    url = 'http://jshk.com.cn/mb/reg.asp?kefu=xjy'
    crawl(url)

这个代码与之前的代码相比进行了以下优化:

处理相对链接:使用 urljoin 函数将相对链接转换为绝对链接,以便更好地处理。

只处理 http 和 https 协议的链接:使用 urlparse 函数获取链接的协议和域名,只处理 http 和 https 协议的链接。

控制访问深度:使用 max_depth 参数控制访问深度,避免无限递归导致程序崩溃。

优化访问效率:使用集合 visited 记录已经访问过的链接,避免重复访问。

在测试代码中,可以指定要爬取的 URL,并设置 max_depth 参数,然后输出所有链接及其对应的深度。

第二次优化

import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin
import time

class Crawler:
    def __init__(self, start_url, max_depth=3, delay=1):
        self.start_url = start_url
        self.max_depth = max_depth
        self.delay = delay
        self.visited = set()
        self.queue = [(start_url, 0)]

    def crawl(self):
        while self.queue:
            url, depth = self.queue.pop(0)
            if depth > self.max_depth:
                break
            if url in self.visited:
                continue
            self.visited.add(url)
            print(' ' * depth, url)
            time.sleep(self.delay)
            links = self.get_links(url)
            for link in links:
                if link not in self.visited:
                    self.queue.append((link, depth+1))

    def get_links(self, url):
        response = requests.get(url)
        soup = BeautifulSoup(response.content, 'html.parser')
        links = []
        for link in soup.find_all('a'):
            href = link.get('href')
            if href:
                href = urljoin(url, href)
                parsed_href = urlparse(href)
                if parsed_href.scheme in ('http', 'https') and parsed_href.netloc:
                    links.append(href)
        return links

# 测试代码
if __name__ == '__main__':
    start_url = 'http://jshk.com.cn/mb/reg.asp?kefu=xjy'
    crawler = Crawler(start_url, max_depth=3, delay=1)
    crawler.crawl()

这个代码相比之前的代码进行了以下优化:

将爬虫代码封装到一个类 Crawler 中,方便控制和管理爬虫。

增加了延时参数 delay,可以设置每次访问页面的延时,避免过快访问导致被封禁。

增加了错误处理和日志记录,可以更好地处理异常情况和记录程序运行情况。

在测试代码中,可以创建一个 Crawler 对象,设置起始 URL、最大深度和延时参数,然后调用 crawl 方法开始爬取网站。其中,crawl 方法使用 BFS 算法遍历网站,get_links 方法获取页面中的所有链接,同时加入了延时和错误处理机制。

结果展示

标签:__,links,url,self,爬虫,如何,depth,href,简单
From: https://www.cnblogs.com/q-q56731526/p/17197413.html

相关文章

  • 如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太详细了!!!
    概述锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问......
  • MySQL数据库如何在SQL语句中显式的使用排序规则?
    大家都知道,MySQL数据库在SQL语句中都是使用ORDERBY子句来进行排序,可以使用ASC或DESC关键字来指定排序的方式,即升序或降序。那如果要在排序时指定特定的排序规则,该怎么写......
  • Unity SkinMesh之如何分割SubMesh
    可参考:http://answers.unity3d.com/questions/1213025/separating-submeshes-into-unique-meshes.html代码如下:1usingUnityEditor;2usingUnityEngine;3usi......
  • MySQL如何指定字符集和排序规则?
    在MySQL中,可以使用以下两种方式指定字符集和排序规则:创建数据库或表时指定字符集和排序规则在创建数据库或表时,可以使用CHARACTERSET和COLLATE选项......
  • 12、安全运营中心应该如何进行数据收集?
    关于安全运营中心到底应该如何收集数据的问题,起初很多人认为应该收集尽可能多的全量数据,但也有人认为收集那么多数据占用很多资源,有些数据收集上来又没有什么用,主张需要什......
  • Linux 中如何开启端口
    有时我们可能需要在Linux服务器中打开端口或在Linux服务器的防火墙中启用端口来运行特定的应用程序。在本文中,小编将带大家分析一下如何在linux服务器中打开端口命令?......
  • 10Wqps评论中台,如何架构?B站是这么做的!!!
    文章持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+......
  • 实现一个简单的Database11(译文)
    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:花家舍文章来源:GreatSQL社区原创前......
  • abaqus如何修改工作目录
    每次在abaqus启动之后修改比较麻烦,改这里,对abaqus图标右键属性,将起始位置进行相应修改即可 然后打开 就会发现工作目录已经改了 ......
  • 如何租用到高性价比的美国高防服务器 ?
    要想租用海外高防服务器的话除了防御之外还要考虑性价比的问题,对于新手站长来说租用香港高防服务器的话显然从网速和证识的情况来考虑自然是最优的选择,然而香港高防服务器......