如何在Java中不依赖第三方库解析HTML并提取内容与URL?
嘿,我懂你现在的处境——要纯原生实现HTML解析,提取标签的URL和对应文本存数据库,而且不能用任何第三方库,对吧?我之前也遇到过类似的需求,给你分享个靠谱的实现思路和代码。
要搞定这个需求,我们可以分两步走:提取标签里的href属性(也就是URL),然后提取标签包裹的有效文本(去掉嵌套的HTML标签,只留纯文本)。
1. 提取标签的URL
HTML里的标签href属性可能有三种写法:双引号包裹、单引号包裹,甚至不包裹(虽然不规范,但实际场景里可能遇到)。我们可以通过字符串匹配来处理这三种情况:
- 先定位到
<a的起始位置,再找到标签闭合的> - 在这个范围内找
href=的位置,然后判断包裹URL的引号类型(或无引号),提取出URL内容
2. 提取标签内的有效文本
标签里可能嵌套其他标签(比如<b>、<i>),我们需要把这些标签都去掉,只保留纯文本:
- 找到
<a>闭合>之后到</a>之前的内容 - 遍历这段内容,把所有
<...>格式的标签都剔除,剩下的就是纯文本 - 最后清理掉多余的空格、换行,让文本更整洁
下面是完整的可运行代码,完全不用第三方库,能处理大部分常见的标签场景:
def extract_links_and_text(html_content): links_data = [] start_pos = 0 html_len = len(html_content) while start_pos < html_len: # 定位下一个<a>标签的起始位置 a_start = html_content.find('<a ', start_pos) if a_start == -1: break # 没有更多<a>标签,结束循环 # 找到当前<a>标签的闭合>位置 a_end = html_content.find('>', a_start) if a_end == -1: start_pos = a_start + 1 continue # 提取href属性 href_start = html_content.find('href=', a_start, a_end) if href_start == -1: # 没有href的<a>标签,直接跳过 start_pos = a_end + 1 continue href_start += len('href=') quote_char = html_content[href_start] # 处理三种href格式:双引号、单引号、无引号 if quote_char in ('"', "'"): href_start += 1 href_end = html_content.find(quote_char, href_start) if href_end == -1: href_end = a_end else: # 无引号的情况,找下一个空格或标签结束位置 href_end = html_content.find(' ', href_start, a_end) if href_end == -1: href_end = a_end url = html_content[href_start:href_end].strip() # 提取<a>标签内的文本内容 closing_a_start = html_content.find('</a>', a_end) if closing_a_start == -1: start_pos = a_end + 1 continue inner_content = html_content[a_end+1:closing_a_start] # 剔除inner_content里的所有HTML标签 pure_text = '' current_pos = 0 inner_len = len(inner_content) while current_pos < inner_len: tag_open = inner_content.find('<', current_pos) if tag_open == -1: pure_text += inner_content[current_pos:] break # 把标签前的文本加进去 pure_text += inner_content[current_pos:tag_open] # 找到标签的闭合> tag_close = inner_content.find('>', tag_open) if tag_close == -1: break current_pos = tag_close + 1 # 清理文本中的多余空格和换行 pure_text = ' '.join(pure_text.split()).strip() # 把结果存入列表,后续可以直接写入数据库 links_data.append({ 'url': url, 'text': pure_text }) # 更新起始位置,继续查找下一个<a>标签 start_pos = closing_a_start + len('</a>') return links_data # 测试用例 sample_html = ''' <!DOCTYPE html> <html> <head><title>Test Page</title></head> <body> <a href="https://example.com">Example Website</a> <a href='https://test.org'>Test <em>Italic</em> Text</a> <a class="nav-link" href=https://noquote.net>No Quotes Here</a> <a href="#section1">Jump to Section 1</a> </body> </html> ''' # 调用函数并打印结果 extracted_data = extract_links_and_text(sample_html) for idx, item in enumerate(extracted_data, 1): print(f"Link {idx}:") print(f" URL: {item['url']}") print(f" Text: {item['text']}\n")
- 这个方法是基于字符串匹配的,适合处理结构不太复杂的HTML文档;如果遇到非常复杂的场景(比如嵌套多层标签、HTML注释、CDATA块等),可能需要写更复杂的状态机来处理,但对于大部分常规需求已经足够。
- 提取到的
links_data是一个字典列表,你可以直接遍历它,把每个字典里的url和text写入数据库(比如用Python的sqlite3模块,也是原生的)。
内容的提问来源于stack exchange,提问作者Scarlet
相关产品推荐
相关产品推荐

