Google Scholar学者爬取:翻页失效与匹配精度问题求助
Google Scholar教授信息爬取问题解决方案
问题概述
需基于研究领域、大学爬取Google Scholar教授信息,使用requests时遭遇429错误,改用urllib后恢复,但存在两个问题:
- 无法自动爬取下一页,循环无法正常终止
- 查询仅支持精确匹配,无法返回子串匹配结果(如搜索"ecology"无法返回研究方向含"Tropical_Forest_Ecology"的学者)
解决方案
1. 修复自动翻页与循环终止逻辑
原代码存在以下问题导致翻页失效:
- 未导入
re模块,正则匹配代码报错 - 未先判断下一页按钮是否存在就直接访问
onclick属性,触发KeyError return语句位置错误,仅处理第一个大学就返回结果- 向
uni字段添加的是整个大学列表而非当前遍历的大学名称
修复要点:
- 导入
re模块 - 先检查下一页按钮是否存在,再提取翻页令牌
- 将
return移至大学循环外部 - 修正
uni字段的赋值逻辑 - 增加空值判断,避免因页面元素缺失触发异常
2. 实现子串模糊匹配
原查询参数mauthors: f'label:{label} "{uni}"'使用双引号实现大学精确匹配,label:限定研究领域为精确标签匹配,导致无法返回子串匹配结果。
调整方案:
- 去掉大学名称的双引号,改为
label:{label} {uni},实现大学名称的包含匹配 - 若需匹配研究兴趣中的子串,去掉
label:前缀,改为"{label}" {uni}或直接{label} {uni},此时Google Scholar会检索研究兴趣、简介等字段中包含该关键词的作者
修正后的完整代码
from bs4 import BeautifulSoup import urllib import re from time import sleep def Scrape_profiles(label, university_name, country): # 存储所有大学的结果 all_results = { 'name': [], 'email': [], 'affiliations': [], 'Citation': [], 'interests': [], 'uni': [], 'country': [] } for uni in university_name: params = { "view_op": "search_authors", # 改为模糊匹配:去掉大学的双引号,若要匹配研究兴趣子串可去掉label:前缀 "mauthors": f'{label} {uni}', "hl": "en", "astart": 0, "engine": "google_scholar_profiles", } while True: url = r"https://scholar.google.com/citations?" data = urllib.parse.urlencode(params) req = urllib.request.Request(url + data, headers={'cookie': '<my cookie>'}) resp = urllib.request.urlopen(req).read() soup = BeautifulSoup(resp, 'html5lib') proftags = soup.findAll("div", {"class": "gsc_1usr"}) for mytag in proftags: # 处理名称 name_tag = mytag.find("h3", {"class": "gs_ai_name"}) all_results['name'].append(name_tag.text if name_tag else "N/A") # 处理邮箱 email_tag = mytag.find("div", {"class": "gs_ai_eml"}) all_results['email'].append(email_tag.text if email_tag else "N/A") # 处理机构 aff_tag = mytag.find("div", {"class": "gs_ai_aff"}) all_results['affiliations'].append(aff_tag.text if aff_tag else "N/A") # 处理引用量 cite_tag = mytag.find("div", {"class": "gs_ai_cby"}) all_results['Citation'].append(cite_tag.text[8:] if cite_tag else "N/A") # 处理研究兴趣 interests = [item.text for item in mytag.findAll("a", {"class": "gs_ai_one_int"})] all_results['interests'].append(interests if interests else ["N/A"]) all_results['uni'].append(uni) all_results['country'].append(country) sleep(0.2) # 处理下一页逻辑 next_btn = soup.select_one("button.gs_btnPR") if next_btn and next_btn.get("onclick"): match = re.search(r"after_author\\x3d(.*?)\\x26", str(next_btn["onclick"])) if match: params["after_author"] = match.group(1) params["astart"] += 10 else: break else: break return all_results # 示例调用 label = "ecology" university_name = ["Michigan University"] country = 'USA' result = Scrape_profiles(label, university_name, country) print(result)
内容的提问来源于stack exchange,提问作者Mohammad Reza
相关产品推荐
相关产品推荐

