如何用Mechanize和BeautifulSoup实现指定矿产地网站分页数据爬取
实现矿物 occurrence 网站的分页数据爬取功能
我来帮你完善这个爬虫,搞定带搜索参数的分页数据获取功能。咱们一步步来,先补全代码里的细节,再实现核心的分页逻辑:
首先,先把初始化部分补全,确保浏览器模拟的配置正确:
import re import mechanize from bs4 import BeautifulSoup class MineralDBScraper(object): def __init__(self): self.url = "http://dnre-mrne.gnb.ca/MineralOccurrence/default.aspx" self.br = mechanize.Browser() # 用完整的User-Agent避免被反爬拦截 self.br.addheaders = [('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36')] # 配置浏览器行为,忽略robots.txt和自动处理刷新 self.br.set_handle_robots(False) self.br.set_handle_refresh(False)
接下来实现搜索提交的方法,用来初始化第一页的搜索结果:
def search(self, ref_number="%"): """提交搜索表单,返回第一页的解析后数据""" # 打开目标页面 self.br.open(self.url) # 选择页面上的第一个表单(也就是搜索表单) self.br.select_form(nr=0) # 注意:这里的表单字段名需要你自己去页面源码里确认! # 打开网页F12查看参考编号输入框的name属性,替换下面的字段名 self.br.form['txtReferenceNumber'] = ref_number # 提交表单获取结果页 response = self.br.submit() return self._parse_page(response.read())
然后写一个私有方法来解析单页的表格数据:
def _parse_page(self, html_content): """解析单页的表格,返回结构化的列表数据""" soup = BeautifulSoup(html_content, 'html.parser') # 同样,表格的id需要你去页面源码确认,这里是假设的id result_table = soup.find('table', {'id': 'gvMineralOccurrence'}) if not result_table: return [] # 跳过表头行,遍历数据行 data_rows = result_table.find_all('tr')[1:] parsed_data = [] for row in data_rows: cols = row.find_all('td') if cols: # 根据表格实际列顺序提取数据,这里是示例结构,你要按需调整 item = { 'reference_number': cols[0].text.strip(), 'property_name': cols[1].text.strip(), 'commodity': cols[2].text.strip(), # 其他字段根据页面表格的列数和内容补充 } parsed_data.append(item) return parsed_data
核心的分页功能来了,实现获取下一页的方法:
def get_next_page(self): """获取下一页数据,没有下一页时返回空列表""" try: # 这里的分页按钮name属性同样需要你去页面源码确认! # 找下一页按钮的name,比如页面里可能是类似 'gvMineralOccurrence$ctl00$ctl04$ctl00$ctl01$ctl00$ctl02' 这样的名字 response = self.br.submit(name='gvMineralOccurrence$ctl00$ctl04$ctl00$ctl01$ctl00$ctl02') return self._parse_page(response.read()) except mechanize.FormNotFoundError: # 捕获找不到下一页按钮的异常,说明已经到最后一页了 return []
最后给你一个完整的使用示例,方便测试:
if __name__ == "__main__": scraper = MineralDBScraper() # 初始搜索,用"%"作为参考编号获取全量结果 first_page = scraper.search(ref_number="%") print(f"第一页数据共 {len(first_page)} 条") # 循环爬取所有分页 all_mineral_data = first_page.copy() while True: next_page_data = scraper.get_next_page() if not next_page_data: print("已爬完所有页面") break print(f"获取到下一页,共 {len(next_page_data)} 条数据") all_mineral_data.extend(next_page_data) print(f"最终总共获取到 {len(all_mineral_data)} 条矿物 occurrence 数据")
关键注意事项
- 字段名确认:一定要自己打开目标页面,用F12查看源码,确认搜索输入框、分页按钮的
name属性,以及结果表格的id,示例里的名字都是假设的,必须替换成真实值才能正常工作。 - 反爬防护:如果爬取频繁被拦截,可以在每次请求后加个延迟(比如
time.sleep(2)),避免触发网站的反爬机制。 - 页面结构变化:如果后续网站更新了页面布局,需要对应调整解析逻辑,比如表格的列顺序、元素的class/id等。
内容的提问来源于stack exchange,提问作者Umesh Pathak
相关产品推荐
相关产品推荐

