2501_93323859 2025-11-08 16:46 采纳率: 25%
浏览 8

爬取网页节点下的所有数据

网页为 “https://www.cnzj5u.com/list_block.aspx?stid=187&rptid=8%E2%80%9D
通过抓包工具能看到用的post请求,post带着stid :187 rptid :8两个参数,会得到一个表单数据。
通过点击下一页抓包工具看到的请求都是一样的,只有表单数据中一个__EVENTTARGET的值会有变化
如何通过代码实现爬取所有的数据

  • 写回答

4条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-11-08 21:38
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案能帮助您,请采纳,非常感谢!
    .
    每日一句正能量,让它带给您好心情:每一次失败,都是成功的伏笔,只要你不放弃。
    .

    爬取网页节点下的所有数据

    根据您提供的信息,这是一个使用POST请求和表单参数进行分页的网页爬取需求。下面我将详细说明如何通过代码实现爬取所有数据。

    分析思路

    1. 该网站使用ASP.NET Web Forms技术,通过POST请求获取数据
    2. 分页通过__EVENTTARGET参数控制,点击不同页码时该值会变化
    3. 需要模拟表单提交来获取每一页的数据

    实现代码

    import requests
    from bs4 import BeautifulSoup
    import time
    import re
    
    
    def crawl_all_data():
        """
        爬取所有页面的数据
        """
        base_url = "https://www.cnzj5u.com/list_block.aspx?stid=187&rptid=8"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        
        # 存储所有数据
        all_data = []
        
        # 首先获取第一页,提取必要的表单数据和总页数
        session = requests.Session()
        first_page_response = session.get(base_url, headers=headers)
        first_page_soup = BeautifulSoup(first_page_response.text, 'html.parser')
        
        # 提取表单数据
        form_data = extract_form_data(first_page_soup)
        
        # 提取总页数
        total_pages = extract_total_pages(first_page_soup)
        print(f"总页数: {total_pages}")
        
        # 爬取每一页
        for page in range(1, total_pages + 1):
            print(f"正在爬取第 {page} 页...")
            
            if page == 1:
                # 第一页数据已经获取,直接解析
                page_data = parse_page_data(first_page_soup)
                all_data.extend(page_data)
            else:
                # 更新页码参数
                form_data['__EVENTTARGET'] = f'Page${page}'
                
                # 发送POST请求
                response = session.post(base_url, data=form_data, headers=headers)
                soup = BeautifulSoup(response.text, 'html.parser')
                
                # 解析数据
                page_data = parse_page_data(soup)
                all_data.extend(page_data)
                
                # 更新表单数据(ASP.NET可能会更新其他隐藏字段)
                form_data = extract_form_data(soup)
            
            # 添加延时,避免请求过于频繁
            time.sleep(1)
        
        return all_data
    
    
    def extract_form_data(soup):
        """
        提取表单中的所有隐藏字段
        """
        form_data = {
            'stid': '187',
            'rptid': '8'
        }
        
        # 提取所有隐藏的input字段
        hidden_inputs = soup.find_all('input', {'type': 'hidden'})
        for input_field in hidden_inputs:
            name = input_field.get('name')
            value = input_field.get('value', '')
            if name:
                form_data[name] = value
        
        return form_data
    
    
    def extract_total_pages(soup):
        """
        提取总页数
        """
        # 查找分页控件,通常包含总页数信息
        pagination = soup.find('div', class_='pagination')  # 根据实际HTML结构调整选择器
        
        if pagination:
            # 查找包含页码的链接或文本
            page_links = pagination.find_all('a')
            if page_links:
                # 获取最后一个页码链接的文本
                last_page_text = page_links[-1].get_text()
                if last_page_text.isdigit():
                    return int(last_page_text)
        
        # 如果无法从分页控件获取,尝试从其他位置获取或设置默认值
        # 这里需要根据实际网页结构调整
        return 10  # 默认值,需要根据实际情况调整
    
    
    def parse_page_data(soup):
        """
        解析单页数据
        """
        page_data = []
        
        # 根据实际HTML结构定位数据行
        # 这里需要根据实际网页结构调整选择器
        data_rows = soup.find_all('tr', class_='data-row')  # 示例选择器
        
        for row in data_rows:
            item_data = {}
            
            # 提取每个字段的数据
            # 这里需要根据实际HTML结构调整
            cells = row.find_all('td')
            if len(cells) >= 3:  # 根据实际列数调整
                item_data['title'] = cells[0].get_text().strip()
                item_data['link'] = cells[0].find('a')['href'] if cells[0].find('a') else ''
                item_data['date'] = cells[1].get_text().strip()
                item_data['category'] = cells[2].get_text().strip()
                
                page_data.append(item_data)
        
        return page_data
    
    
    # 执行爬取
    if __name__ == "__main__":
        try:
            all_data = crawl_all_data()
            print(f"共爬取 {len(all_data)} 条数据")
            
            # 保存数据到文件
            import json
            with open('crawled_data.json', 'w', encoding='utf-8') as f:
                json.dump(all_data, f, ensure_ascii=False, indent=2)
            
            print("数据已保存到 crawled_data.json")
            
        except Exception as e:
            print(f"爬取过程中出现错误: {e}")
    

    关键点说明

    1. 表单数据处理
    • 需要提取所有隐藏字段(如__VIEWSTATE, __EVENTVALIDATION等)
    • 这些字段在每次请求后可能会更新
    1. 分页控制
    • __EVENTTARGET参数控制分页,格式通常为Page$页码
    • 需要先获取总页数来确定循环范围
    1. 会话保持
    • 使用requests.Session()保持会话状态
    • ASP.NET应用通常需要维护会话状态

    注意事项

    1. 选择器调整:代码中的CSS选择器需要根据实际网页HTML结构调整
    2. 反爬措施:适当添加延时,避免请求过于频繁
    3. 错误处理:添加适当的异常处理机制
    4. 合法性:确保爬取行为符合网站的robots.txt和相关法律法规

    调试建议

    1. 使用浏览器开发者工具观察网络请求
    2. 先测试单页爬取,确认选择器正确
    3. 逐步增加页码,验证分页逻辑

    请根据实际网页结构调整代码中的选择器和解析逻辑。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月8日