python学习心得

        2025.3.4

再跑cic网站的爬虫Index of /,想把所有目录的文件统计一下大小但遇到几个问题,可见下面的prompt

我现在想把这个网站上的所有文件夹里的数据都统计一遍大小,但是手动操作比较慢,http://cicresearch.ca/,请注意:1.这个网站的http://cicresearch.ca/CICDataset/和http://cicresearch.ca/IOTDataset/两个二级目录,由二级目录到三级目录时要填写表单,但可以通过在三级目录后加上/Dataset,跳过表单,直接进入三级目录(由于三级目录后已加上/Dataset,故每个三级目录对应一个四级目录)2.这个网站在进入http://cicresearch.ca/Large%20Language%20Model%20datasets/这个二级目录时,也需要同样的操作,如http://cicresearch.ca/Large%20Language%20Model%20datasets/Dataset才可正常访问这个目录,请你写一个爬虫脚本,把每个文件的大小和地址、上传时间等元素,通过json格式给我,并统计总大小

把claude的代码经过修改后确实可以了。下面开始读代码,记录一些python用法:

1.quote用来将字符串转换为适合在 URL 中使用的格式 ,比如把%20替换成空格,来自url.parser库,这里的.replace(" ", "%20")可以去掉,是多余的

    def should_add_dataset_suffix(self, url):
        """判断是否需要添加Dataset后缀"""
        for special_dir in self.special_dirs:
            if special_dir in url:
                # 如果是二级目录,直接添加Dataset
                if url.rstrip('/') == self.base_url + quote(special_dir).replace(" ", "%20"):
                    return True
                
                # 如果是三级目录,也添加Dataset
                parts = url.rstrip('/').split('/')
                if len(parts) > 4 and special_dir in parts[3]:
                    # 确保不是已经有Dataset的URL
                    if not url.endswith('/Dataset/') and 'Dataset' not in url.split('/')[-8:]:
                        return True
        
        return False

2.判断三级子目录时,为什么len(parts)>4就说是三级目录呢:若len(parts)为5,那么此时对应的目录就成为:http://cicresearch.ca/part1/part2/,正好是三级目录。这里要注意,两个相邻的/会被切出一个空字符串,但也占一个长度。

url="http://cicresearch.ca/part1/part2/part3"
parts=url.rstrip('/').split('/')
print(parts)
输出:
['http:', '', 'cicresearch.ca', 'part1', 'part2', 'part3']

3.

if not url.endswith('/Dataset/') and 'Dataset' not in url.split('/')

这段代码有点意思  ,首先,not的优先级比and高,所以先判断两个条件

其次,not的位置可变,上面代码等价于下面的代码

if not url.endswith('/Dataset/') and  not 'Dataset'  in url.split('/')

2025.3.5

    def parse_apache_directory(self, url, html):
        """解析Apache目录列表"""
        soup = BeautifulSoup(html, 'html.parser')
        items = []
        
        # 查找表格 - Apache目录列表通常使用表格布局
        table = soup.find('table')
        if table:
            rows = table.find_all('tr')
            print(f"发现table,有 {len(rows) - 3} 个项目")
            # 跳过标题行
            for row in rows[1:]:
                cells = row.find_all(['td', 'th'])
                if len(cells) < 3:
                    continue
                
                # 获取名称、最后修改时间和大小
                name_cell = cells[1]
                date_cell = cells[2]
                size_cell = cells[3]
                
                link = name_cell.find('a')
                if not link:
                    continue
                
                name = link.text.strip()
                if name == "Parent Directory" or name == "..":
                    continue
                
                href = link.get('href')
                full_url = urljoin(url, href)
                is_dir = href.endswith('/')
                
                last_modified = date_cell.text.strip()
                size_text = size_cell.text.strip()
                size_bytes = 0 if is_dir else self.parse_size(size_text)
                
                item = {
                    "name": name,
                    "url": full_url,
                    "is_directory": is_dir,
                    "last_modified": last_modified,
                    "size_text": size_text if not is_dir else "-",
                    "size_bytes": size_bytes
                }
                
                items.append(item)
        
        return items

1.这里进入了解析html的部分,先解析apache的 表格布局,用soup.find()先找出table,再找出每行元素rows,标识符为'tr',项目应该有tr数量减三个,因为table上下各有一条横线,占2个tr,上面还有标题栏,占一个tr。

ps:刚才发现无论怎么算,代码运行出来都多一个tr,后来刷新了网页,发现网页更新了,网站多加了一个html文件...

2.开始找td、th标签,

  • td 代表 "table data"(表格数据)。
  • th 代表 "table header"(表格头部)。

过滤掉那些单元格数量少于 3 个的行,通常这些行不包含有效数据

cell[0]是图标,cell[1]是名称,cell[2]是日期,cell[3]是大小

有'a'标签代表是一个超链接,可点击跳转。若不是超链接,就退出循环 


                # 获取名称、最后修改时间和大小
                name_cell = cells[1]
                date_cell = cells[2]
                size_cell = cells[3]
                
                link = name_cell.find('a')
                if not link:
                    continue
                
                name = link.text.strip()
                if name == "Parent Directory" or name == "..":
                    continue

link.text会去掉a标签的内容,只保留文本部分

link.get('href)获取下一级的链接,拼上就是完整的连接了 

判断是不是文件夹,只需要看末尾有没有/

3.response是获取get方法的响应

       try:
            # 添加随机延迟避免请求过快
            time.sleep(random.uniform(0.1, 0.3))
            
            response = requests.get(url, headers=self.headers, timeout=30)
            if response.status_code == 404:
                print(f"页面不存在: {url}")
                return
            
            response.raise_for_status()#来判断请求是否成功,如果成功则继续执行,否则抛出异常
            
            # 检查是否是Apache目录列表
            if "Index of" in response.text and "Apache" in response.text:
                items = self.parse_apache_directory(url, response.text)
                
                for item in items:
                    if item["is_directory"]:
                        # 递归爬取子目录
                        self.crawl_directory(item["url"])
                    else:
                        # 添加文件到结果
                        self.results["files"].append(item)
                        self.results["total_size_bytes"] += item["size_bytes"]
                        print(f"发现文件: {item['name']} - {item['size_text']}")
            else:
                # 不是Apache目录列表,尝试从HTML中提取链接
                soup = BeautifulSoup(response.text, 'html.parser')
                links = soup.find_all('a')

对于每个item,如果是目录的话,就用当前item的url继续递归,深度优先遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值