第15期 Python实现Pubmed论文信息批量抓取

本期介绍一个放入pubmed的当前网址,就循环翻页抓取论文的题目,摘要,作者,doi分区等各种信息的python脚本

主要看看总代码复制就行

1 结果展示

抓取界面

数据界面

2 总代码


from pyquery import PyQuery
from requests.exceptions import SSLError
import requests
import json
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import time

def pubmed_url(url_pubmed,pagenum):
    session = requests.Session()
    retries = Retry(total=5, 
                    backoff_factor=1, 
                    status_forcelist=[500, 502, 503, 504])
    session.mount('https://', HTTPAdapter(max_retries=retries))
    n=1
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)   \
                           AppleWebKit/537.36 (KHTML, like Gecko)  \
                           Chrome/92.0.4515.131 Safari/537.36'}
    bookinfo_list=[]
    for i in range(1,pagenum+1):
            url = url_pubmed+"&page={page}".format(page=i)
            resp = session.get(url, headers=headers)
            html = resp.text
            doc = PyQuery(html)
            for article in doc.items(".docsum-content"):
                try:
                    article_url = article("a").attr("href")
                    url = f'https://pubmed.ncbi.nlm.nih.gov{article_url}'
                    resp_temp = requests.get(url,headers=headers)
                    html_temp = resp_temp.text
                    doc_temp = PyQuery(html_temp)
                    abstract=doc_temp(".article-page .abstract.abstract p").text()
                    other=doc_temp(".article-details .heading .full-view .article-citation .article-source .cit").text()
                    book_name=article(".docsum-title").text()
                    doi=doc_temp(".article-details .heading .full-view .id-link").text()
                    #doi_address=f"=HYPERLINK(\"https://sci-hub.se/{doi.replace('/', '_')}\",\"{book_name}\")"
                    book_author=article(".full-authors").text()
                    book_PMId=article(".docsum-pmid").text()
                    book_qita_qita=article(".short-journal-citation").text().split(".")[0]
                    book_qita_year=article(".short-journal-citation").text().split(".")[1]
                    # API的URL
                    url_easy = 'https://www.easyscholar.cc/open/getPublicationRank'
                    # 需要发送的参数
                    params = {
                        'secretKey': '851c43e2c9f040c3b95cb64e31252454',
                        'publicationName': book_qita_qita
                    }
                    # 发送GET请求
                    response_easy = requests.get(url_easy, params=params)
                    # 解析JSON
                    parsed_json = json.loads(response_easy.text)
                    # 提取data中的officialRank下的all
                    official_rank_all = parsed_json['data']['officialRank']['all']
                    # 生成所需的字符串格式
                    rank_strings = "\n".join([f"{key.upper()}: {value}" for key, value in official_rank_all.items()])
                    ref = [ref.text() for ref in doc_temp(".articles-list .full-docsum .docsum-title").items()]
                    ref_text = '\n'.join(ref) 
                    print("第",i,"页   ","第",n,"篇", "   ",book_name)
                    bookinfo = {'book_name':book_name,
                                    "year":book_qita_year,
                                    "abstract":abstract,
                                    "journal":book_qita_qita,
                                    "rank":rank_strings,
                                    'authors':book_author,
                                    "PMID":book_PMId,
                                    "doi":doi,
                                    "other":other,
                                    "ref":ref_text
                                    #"full_text":doi_address
                                    }
                    bookinfo_list.append(bookinfo)
                    n=n+1
                    time.sleep(5)
                except SSLError as e:
                    print(f"SSL 错误发生在获取页面时: {e}")
                    continue

                # 可以在这里添加其他类型的异常处理,如果需要
                except Exception as e:
                    print(f"其他错误发生: {e}")
                    continue
    return bookinfo_list



result_list =  pubmed_url('https://pubmed.ncbi.nlm.nih.gov/?term=micro&sort=date',3)


3 代码剖析

前期准备

  • python环境
  • 需要有easyscholar密钥抓取论文的分区评级和影响因子,申请方式见第8期推文

导入包

导入网页解析包pyquery(bs也可以,没有做)

导入request请求模块

设置retries,用于提高爬虫稳定性

设置请求headers

循环主体

  1. 循环因子是面数
  2. 在每一面先通过request申请到网页内容
  3. 实用pyquery包解析,方便元素的提取
  4. 查看网页的元素信息。发现论文的列表可以通过css选择器(.article-content)获取
  5. 遍历每一个论文,抓取题目等表信息
  6. 根据每个论文的href属性,抓取该论文的主页网址
  7. 访问主页网址,并根据css选择器(需自行学习),获取摘要和DOI号等信息
  8. 抓取到DOI后使用json模块,访问easyschlar官网,获取论文的分区和影响因子
  9. 将论文信息保存到字典,后缀到列表中
  • 使用except,抓取错误信息,保证循环顺利进行

论文保存,使用pandas模块进行数据导出

注意事项

  • 输入为:两个参数 par1 当前页面的网址(为了避免太多参数)。 par2:需要获取的页数
    • 进入pubmed,进行检索,复制上方窗口网址(注意网址不要带&page=0,有的话删掉再放进函数)
  • 可进行操作的点
    • 在框架下,根据CSS选择器可自定义抓取哪些元素并排序