Использование Bio Python, Как напечатать ссылки DOI в одной строке (с разделителями-запятыми) для заданной пары поисковых терминов, а не в нескольких строках? - PullRequest
0 голосов
/ 02 марта 2020

Люди из StackOverflow, прежде всего, спасибо за ваше терпение. Я понимаю, что это моя третья тема по этому вопросу, но, поскольку я никуда не деться, и я даже не знаю, с чего начать (я не знаю, чего я не знаю), я решил спросить здесь тем не мение. Я пытаюсь извлечь ссылки из PM C, используя Bio python, чтобы записать обратно в файл CSV, состоящий, среди прочего, из названия растения, связанного заболевания / состояния, которое он лечит / его лекарственного действия, и URL-адреса DOI, которые относятся к данной паре «болезнь растений». После долгих часов попыток понять, что делать и обсудить код с людьми, намного более опытными, чем я, это то, что было наконец напечатано в коде Visual Studio:

  for plant, disease in plant_disease_list:
    search_query = generate_search_query(plant, disease)
    handle1 = Entrez.esearch(db="pmc", term=search_query, retmax="10")
    record1 = Entrez.read(handle1)
    pubmed_ids = record1.get("IdList")
    if len(pubmed_ids)==0:
      print("{}, {}, None".format(plant, disease))
    else:
      for pubmed_id in pubmed_ids:
        handle2 = Entrez.esummary(db="pmc", id=pubmed_id)
        records = Entrez.read(handle2)
        for record in records:
          doi = record.get("DOI")
          if doi is None:
           print(("{}, {}".format(plant, disease)))
          else:
            doi_main = doi.split()
            string = "http://doi.org/"
            to_add = (",").join((string + x) for x in doi_main)
            print("{}, {},".format(plant, disease), to_add, sep="")

, где ранее был определен generate_search_query как:

def generate_search_query(plant, disease):
  search_query = '"{}" AND "{}"'.format(plant, disease)
  return search_query

Это вывод, который я получаю:

Asystasia salicifalia, Puerperal illness, None
Asystasia salicifalia, Puerperium, None
Asystasia salicifalia, Puerperal disorder, None
Barleria strigosa, Tonic
Justicia procumbens, Lumbago, None
Justicia procumbens, Itching,http://doi.org/10.1673/031.012.0501
Strobilanthes auriculata, Malnutrition, None
Thunbergia laurifolia, Detoxificant, None
Thunbergia similis, Tonic, None
Lannea coromandelica, Dizziness,http://doi.org/10.3897/phytokeys.102.24380
Lannea coromandelica, Dizziness,http://doi.org/10.1186/s13002-016-0089-8
Lannea coromandelica, Dizziness,http://doi.org/10.1186/s13002-015-0033-3
Spondias pinnata, Flatulence,http://doi.org/10.1016/j.heliyon.2019.e02768
Spondias pinnata, Flatulence,http://doi.org/10.1186/s13002-019-0287-2
Spondias pinnata, Flatulence,http://doi.org/10.1186/s13002-018-0248-1
Spondias pinnata, Flatulence,http://doi.org/10.3897/phytokeys.102.24380
Spondias pinnata, Flatulence,http://doi.org/10.1155/2018/5382904
Spondias pinnata, Flatulence,http://doi.org/10.1186/s13002-016-0089-8
Spondias pinnata, Flatulence,http://doi.org/10.1186/s13002-015-0033-3
Spondias pinnata, Flatulence,http://doi.org/10.1186/1472-6882-13-243
Spondias pinnata, Flatulence,http://doi.org/10.1186/1472-6882-10-77
Holarrhena pubescens, Diarrhoea,http://doi.org/10.5455/javar.2019.f379
Holarrhena pubescens, Diarrhoea,http://doi.org/10.1155/2019/2321961
Holarrhena pubescens, Diarrhoea,http://doi.org/10.1186/s12906-018-2348-9
Traceback (most recent call last):
  File "scraperscript_python.py", line 33, in <module>
    handle2 = Entrez.esummary(db="pmc", id=pubmed_id)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\site-packages\Bio\Entrez\__init__.py", line 334, in esummary
    return _open(cgi, variables)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\site-packages\Bio\Entrez\__init__.py", line 569, in _open
    handle = _urlopen(cgi)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 525, in open
    response = self._open(req, data)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 543, in _open
    '_open', req)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 503, in _call_chain
    result = func(*args)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 1362, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 1319, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1252, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1298, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1247, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1026, in _send_output
    self.send(msg)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 966, in send
    self.connect()
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1422, in connect
    server_hostname=server_hostname)
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 423, in wrap_socket
    session=session
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 870, in _create
    self.do_handshake()
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 1139, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

, где остальная часть вывода была прервана мной, потому что я не хочу, чтобы он запускался на всех данных, поскольку это печатает это в неправильной форме. Как вы можете видеть на примере Spondias pinnata и метеоризма, вы можете увидеть, как он печатает разные URL-адреса DOI в разных строках. Проблема в том, что я не хочу, чтобы это печаталось так, потому что будет очень трудно вернуть его в исходные данные. Этот CSV-файл, например, содержит только 65 записей, но есть наборы данных с более чем 8000 записей, что делает его очень сложной задачей. Результат, который я получу sh для достижения, должен, например, выглядеть следующим образом (когда мы рассматриваем вышеупомянутую пару «болезнь растений»):

Spondias pinnata, Flatulence, http://doi.org/10.1016/j.heliyon.2019.e02768, http://doi.org/10.1186/s13002-019-0287-2, http://doi.org/10.1186/s13002-018-0248-1, http://doi.org/10.3897/phytokeys.102.24380, http://doi.org/10.1155/2018/5382904, http://doi.org/10.1186/s13002-016-0089-8, http://doi.org/10.1186/s13002-015-0033-3, http://doi.org/10.1186/1472-6882-13-243, http://doi.org/10.1186/1472-6882-10-77

Кто-то из моей семьи предложил мне использовать вложенный словарь, но я не вижу, как / если это поможет, и я понятия не имею, где разместить его в коде и какие изменения внести в и без того сильно вложенные циклы. Любая помощь с этим будет принята с благодарностью. Спасибо.

1 Ответ

1 голос
/ 02 марта 2020

Следующий код:

from Bio import Entrez
import csv
Entrez.email = "theofficialvelocifaptor@gmail.com"


botanical_names = ['Asystasia salicifalia', 'Asystasia salicifalia', 'Asystasia salicifalia', 'Barleria strigosa', 'Justicia procumbens', 'Justicia procumbens', 'Strobilanthes auriculata', 'Thunbergia laurifolia', 'Thunbergia similis', 'Lannea coromandelica', 'Spondias pinnata']
diseases = ['Puerperal illness', 'Puerperium', 'Puerperal disorder', 'Tonic', 'Lumbago', 'Itching', 'Malnutrition', 'Detoxificant', 'Tonic', 'Dizziness', 'Flatulence']

assert len(botanical_names) == len(diseases)

plant_disease_list = zip(botanical_names, diseases)


with open('plant_diseases.csv', 'w', newline='') as csvfile:
    fieldnames = ['plant', 'disease', 'dois']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()

    for plant, disease in plant_disease_list:
      result = {'plant': plant,
                'disease': disease}
      search_query = '"{}" AND "{}"'.format(plant, disease)
      handle1 = Entrez.esearch(db="pmc", term=search_query, retmax="10")
      record1 = Entrez.read(handle1)
      pubmed_ids = record1.get("IdList")
      if pubmed_ids:
        handle2 = Entrez.esummary(db="pmc", id=','.join(pubmed_ids))
        records = Entrez.read(handle2)
        dois = [record.get("DOI") for record in records if record.get("DOI")  is not None]
        prefix = "http://doi.org/"
        dois = ','.join([prefix + doi for doi in dois])
        result['dois'] = dois
      writer.writerow(result)

записывает следующий вывод в файл plant_diseases.csv:

plant,disease,dois
Asystasia salicifalia,Puerperal illness,
Asystasia salicifalia,Puerperium,
Asystasia salicifalia,Puerperal disorder,
Barleria strigosa,Tonic,
Justicia procumbens,Lumbago,
Justicia procumbens,Itching,http://doi.org/10.1673/031.012.0501
Strobilanthes auriculata,Malnutrition,
Thunbergia laurifolia,Detoxificant,
Thunbergia similis,Tonic,
Lannea coromandelica,Dizziness,"http://doi.org/10.3897/phytokeys.102.24380,http://doi.org/10.1186/s13002-016-0089-8,http://doi.org/10.1186/s13002-015-0033-3"
Spondias pinnata,Flatulence,"http://doi.org/10.1016/j.heliyon.2019.e02768,http://doi.org/10.1186/s13002-019-0287-2,http://doi.org/10.1186/s13002-018-0248-1,http://doi.org/10.3897/phytokeys.102.24380,http://doi.org/10.1155/2018/5382904,http://doi.org/10.1186/s13002-016-0089-8,http://doi.org/10.1186/s13002-015-0033-3,http://doi.org/10.1186/1472-6882-13-243,http://doi.org/10.1186/1472-6882-10-77"

Обратите внимание, что я использовал модуль csv для создания действительные файлы CSV . Это включает добавление двойных qoutes вокруг вашего разделенного запятыми списка DOI, чтобы отделить их от запятой, которую вы используете, чтобы очертить растение и болезнь. Кроме того, нет необходимости добавлять заполнитель None, если у вас нет DOI. Поскольку в первой строке содержится заголовок, модуль csv знает, что он должен искать три поля в строке.

Кроме того, не используйте string в качестве имени переменной, поскольку это имя Python модуля в стандартной библиотеке .

...