数据抓取 --Beautiful Soup库的使用问题(2) 使用 find_all,Tag 和 find 基本解决爬虫中的95%以上有难度的需求

本文分享了使用find_all、Tag和find等方法结合正则表达式进行高效数据抓取的经验,通过多个代码案例详解如何定位并解析网页元素,适用于复杂场景下的数据采集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

学习完爬虫后很多小朋友会发现,大部分单一的方法是爬不到想要的数据。必须要混合使用才能解决问题。就如同高考的难题如果只用一种公式和知识点的话,大部分是做不出来的。本人基本使用 find_all,Tag 和 find  基本解决爬虫中的95%以上的需求。剩下的需求,基本用正则也就能解决了。

解释

下面是爬取某个网站商品信息和库存的完整代码。(顺便说一下,这个网站可以给公司带来300多万的营收,有兴趣知道背后的逻辑可以留言给我) 基础知识点没有过关的,先查资料,这里不多解释。

 

代码案例一:

            type_item = soup.find_all('li', class_='breadcrumb-item')
            for i in range(2):
                type1_item = type_item[0].a.get_text()  # 3.一级品类
                type2_item = type_item[1].a.get_text()  # 4.一级品类

逻辑: find_all  +  tag 

解释: 通过 find_all 到所有 包含 class='breadcrumb-item'  的<li> 下的文本,然后通过  TAG 找到 对应的文本。

(要使用 for 循环。)

 

代码案例二:

        chicun = soup.table.tbody.find_all('tr')  # 16-17.不同尺码的库存
        for i in range(len(chicun)):
            size = chicun[i].th.get_text()
            size_number = chicun[i].td.get_text()

逻辑: find_all  +  tag 

解释: 通过 find_all 到所有 <tr> 下的文本,然后通过  TAG 找到 对应的文本。

(要使用 for 循环)

代码案例三:

  ue_price = int(soup.find('div', class_='tprice').span.get_text().replace('€', ''))  # 10.欧洲价格€

逻辑: find +  tag 

解释: 通过 find 到包含 class='tprice' 的<div> 下的文本,然后通过  TAG 找到 对应的文本。

 

 

总结

基本上难定位到的元素,使用find_all,Tag 和 find的组合大部分都能解决的。 (这里就不多举案例了,有需要更多案例的或者不清楚的就留言给我)

 

 

完整代码如下:

import random
import requests
from bs4 import BeautifulSoup
import chardet
import re
import pymysql
from datetime import *


USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
    'Opera/8.0 (Windows NT 5.1; U; en)',
    'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
    'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
    'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
    'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
    'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)',
    'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36'
]
url_list = []
# Section1
# 爬取013的url_链接,先将爬取URL放入URL列表内
# begin------------------------------------------------------------------------------------------------------------------
for page in range(1,80):
    url = 'http://www.yvogue.com/product/search?pageNo={}'.format(page)

    print('正在爬取url:', url)
    try:
        headers = {
            'user-agent': random.choice(USER_AGENTS)}  # 随机选取代理的AGENT
        response = requests.get(url=url, headers=headers, timeout=30)
        response.encoding = chardet.detect(response.content)['encoding']
        text = response.text
        soup = BeautifulSoup(text, 'lxml')

        url_group = soup.find_all('h6')
        for i in range(len(url_group)):
            url = url_group[i].a.get('href').replace('detail','http://www.yvogue.com/product/detail')
            url_list.append(url)
    except:
        print('提取失败,失败页面为:', url)
url_list = list(set(url_list))
print(url_list)
print('总共爬取的SKU数量是:',len(url_list))
#爬取SKU的链接结束
#--------------------------------------------------------------------------------------------------------------------end

# Section2
# 爬取品牌列表----------------------------------------------------------------------------------------------------------begin
url_brand ='http://www.yvogue.com/product/search'
brand_list_result = []
headers = {
    'user-agent': random.choice(USER_AGENTS)}  # 随机选取代理的AGENT
response = requests.get(url=url_brand, headers=headers, timeout=30)
response.encoding = chardet.detect(response.content)['encoding']
text = response.text
soup = BeautifulSoup(text, 'lxml')
brand_list = soup.find_all('a',attrvaltarget='brandId')
for i in range(len(brand_list)):
    mm = brand_list[i].span.get_text()
    nn = brand_list[i].span.get_text().lower()
    kk = brand_list[i].span.get_text().lower()
    brand_list_result.append(nn)
    brand_list_result.append(mm)
    brand_list_result.append(kk)
brand_list_result = list(set(brand_list_result))
print(brand_list_result)
print(len(brand_list_result))

# 品牌列表爬取完毕-----------------------------------------------------------------------------------------------------end


#Section3 : 根据已经有的URL和品牌列表,爬取和清洗数据,并写入数据库内。
url_fail=[]

for url in url_list:
    try:
        headers = {
            'user-agent': random.choice(USER_AGENTS)}  # 随机选取代理的AGENT
        response = requests.get(url=url, headers=headers, timeout=60)
        response.encoding = chardet.detect(response.content)['encoding']
        text = response.text
        soup = BeautifulSoup(text, 'lxml')

        url = url  # 1.url 链接

        type_of_size = soup.table.th.get_text() # 2.尺寸标准,均码的话就是TU
        try:
            type_item = soup.find_all('li', class_='breadcrumb-item')
            for i in range(2):
                type1_item = type_item[0].a.get_text()  # 3.一级品类
                type2_item = type_item[1].a.get_text()  # 4.一级品类
        except:
            type1_item = '系统无数据'
            type2_item = '系统无数据'

        product_name = soup.find('div', class_='mainname heading-block topmargin-sm').h4.get_text()  # 5.品名:包含品牌和货号

        for brand_excample in brand_list_result:
            if brand_excample in product_name:
                brand = brand_excample  # 6.品牌
                sku_code = product_name.replace(brand_excample, '')  # 7.商品货号 可能部分没法完整的更新。

        retail_price = int(
            soup.find('div', class_='mprice').span.get_text().replace('$', '').replace(' ', ''))  # 8.013的零售价
        supply_price = int(retail_price * 0.7)  # 9.013的大概供货价

        ue_price = int(soup.find('div', class_='tprice').span.get_text().replace('€', ''))  # 10.欧洲价格€

        supplier = '013'  # 11.供应商013

        repl = [' ', '.', '_', '£', '#', '%', '&', '!', '/', '@', '$', '^', '`', '~', '+', '=', '(', ')', ')', '?','-']
        filter_sku_code = sku_code.upper().replace('O', '0').replace('I', '1').replace('Z', '2')
        for f in range(len(repl)):
            filter_sku_code = filter_sku_code.replace(repl[f], '')  # 12.主键货号(过滤后的货号)

        picture_org = soup.find('div', class_='selectors').find_all('a')
        # 提取图片-----------------------------------------------------------------------------------begin        #13.图片 1-9
        picture = ['pic1', 'pic2', 'pic3', 'pic4', 'pic5', 'pic6', 'pic7', 'pic8', 'pic9']

        for i in range(9):
            try:
                picture[i] = picture_org[i].get('href')
            except:
                picture[i] = ''
        # 提取图片结束--------------------------------------------------------------------------------end

        crawl_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # 14.爬取的时间
        task_id = datetime.now().strftime('%Y-%m-%d')  # 15.task_id

        chicun = soup.table.tbody.find_all('tr')  # 16-17.不同尺码的库存
        for i in range(len(chicun)):
            size = chicun[i].th.get_text()
            size_number = chicun[i].td.get_text()

            # 写入数据库
            # begin----------------------------------------------------------------------------------------------------------
            conn = pymysql.connect(host='rm-bp196rexhw26efmo.mysql.rds.aliyuncs.com', user='evan_junhui',
                                   password='mima',
                                   db='supplier', port=3306, charset='utf8')
            cursor = conn.cursor()

            sql = '''insert into supplier_013 (url,type_of_size,type1_item,type2_item,product_name,brand,sku_code,retail_price,supply_price,ue_price,supplier,filter_sku_code,pic1,pic2,pic3,pic4,pic5,pic6,pic7,pic8,pic9,crawl_time,task_id,size,size_number) 
                                                                    values ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')''' % (
                url, type_of_size, type1_item, type2_item, product_name, brand, sku_code, retail_price, supply_price,
                ue_price, supplier, filter_sku_code, picture[0], picture[1],
                picture[2], picture[3], picture[4], picture[5], picture[6], picture[7], picture[8], crawl_time, task_id,
                size, size_number)                                                                                       # 一定要使用,不然会出现解析失败
            try:
                cursor.execute(sql)
                conn.commit()
                print('数据写入成功')
            except:
                cursor.rollback()
                print('写入失败')
            cursor.close()
            conn.close()
            # -----------------------------------------------------------------------------------------------------------end
    except:
        print('爬取:', url, '失败,')
        url_fail.append(url)

print('爬取失败的SKU数量是',len(url_fail))
print(url_fail)

 

 

 

 

 

<think>好的,用户让我解释这两行代码:`table = soup.find('table', class_='history-table')` `rows = table.find_all('tr')`。首先,我需要确认用户对Beautiful Soup的了解程度。他们可能正在学习网页爬虫使用Beautiful Soup来解析HTML。 用户之前问过关于提取表格数据的代码,所以这次的问题可能是在之前的基础上进一步解析HTML结构。他们可能想知道如何定位特定的表格以及如何获取行数据。 首先,第一行代码使用`soup.find()`方法查找带有特定class的table标签。这里的`class_='history-table'`需要注意,因为`class`是Python的保留字,所以Beautiful Soup用`class_`来代替。用户可能需要了解如何正确指定类名,尤其是当类名包含空格或其他特殊字符时的处理方式。 接下来是第二行代码,`table.find_all('tr')`,这会在找到的表格中提取所有的`<tr>`标签,也就是表格的行。用户可能想知道`find_all``find`的区别,这里需要解释清楚`find`返回第一个匹配的元素,而`find_all`返回所有匹配的列表。 用户可能遇到的问题包括:表格是否存在,class名称是否正确,或者HTML结构是否有嵌套表格。需要提醒他们注意异常处理,比如当`table`为None时,后续代码会出错,所以应该添加检查。 另外,用户可能想知道如何进一步处理这些行数据,比如提取表头单元格,这可能他们之前的代码有关联。需要确保他们理解整个流程:定位表格→获取行→处理每一行的数据。 总结来说,我需要分步骤解释这两行代码的作用,强调关键方法参数,可能的问题解决方案,并关联到实际应用场景,比如数据爬取中的表格提取。同时,结合他们之前的提问,提供连贯的知识点,帮助他们构建完整的解析流程。</think>以下是对代码的详细解析: --- ### **一、代码核心作用** **定位并提取HTML文档中特定表格的所有行数据**,是网页爬虫处理表格数据的典型操作流程。 --- ### **二、代码逐行解析** #### 1. 定位目标表格 ```python table = soup.find('table', class_='history-table') ``` - **`soup`**: 经过BeautifulSoup解析的HTML文档对象 - **`.find()`方法**: - 功能:查找**第一个**匹配条件的标签 - 参数解析: - `'table'`: 指定查找`<table>`标签 - `class_='history-table'`: 匹配`class`属性为"history-table"的表格(注意`class_`的下划线是为避免与Python关键字冲突) - **返回值**:返回一个Tag对象,即找到的整个表格结构 #### 2. 提取所有行 ```python rows = table.find_all('tr') ``` - **`.find_all()`方法**: - 功能:查找**所有**匹配条件的标签 - `'tr'`参数:定位表格行标签 - **返回值**:包含所有`<tr>`标签的ResultSet对象(类似列表) --- ### **三、执行过程示例** 假设原始HTML结构: ```html <table class="history-table"> <tr> <!-- 表头 --> <th>日期</th> <th>事件</th> </tr> <tr> <!-- 数据--> <td>2023-01-01</td> <td>系统上线</td> </tr> <tr> <td>2023-02-15</td> <td>版本更新</td> </tr> </table> ``` 执行结果: - `table`变量:包含整个`<table class="history-table">`标签及其子元素 - `rows`变量:包含3个`<tr>`标签的列表 --- ### **四、关键方法对比** | 方法 | 作用范围 | 返回结果 | 典型应用场景 | |-------------------|------------|-----------------|-----------------------| | `.find()` | 首个匹配元素 | 单个Tag对象 | 定位唯一存在的元素 | | `.find_all()` | 所有匹配元素 | ResultSet列表 | 批量提取同类元素 | --- ### **五、异常处理建议** #### 1. 预防`None`值报错 ```python # 检查是否成功找到表格 if table is None: raise ValueError("未找到class为history-table的表格") # 检查是否包含有效行 if not rows: raise ValueError("表格中未包含有效行数据") ``` #### 2. 处理动态class名 ```python # 使用CSS选择器应对复杂class情况 table = soup.select_one('table[class*="history-table"]') # 包含特定字符的class ``` --- ### **六、典型应用场景** 1. **数据采集**:抓取电商价格历史记录 2. **信息监控**:爬取股票交易数据表 3. **竞品分析**:提取竞争对手产品参数表格 --- ### **七、扩展知识** #### 1. 嵌套表格处理 ```python # 如果需要处理多层嵌套表格 inner_tables = table.find_all('table') # 获取当前表格内的所有子表格 ``` #### 2. 性能优化技巧 ```python # 限制搜索深度提升速度 table = soup.find('table', class_='history-table', recursive=False) # 仅搜索直接子节点 ``` --- ### **八、关联操作流程图** ```mermaid graph TD A[加载HTML文档] --> B[创建BeautifulSoup对象] B --> C{定位目标表格} C -->|成功| D[提取所有行] C -->|失败| E[抛出异常] D --> F[逐行处理数据] ``` 通过这个代码段,我们可以精准定位特定结构的HTML表格,并为后续的数据提取打下基础。建议在实际使用中配合异常处理机制,增强代码的健壮性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值