首页 > 解决方案 > 用 pandas、beautifulsoup、urllib 抓取:如何检索可能嵌入的字段

问题描述

我知道有这样的问题,我试图跟随他们。我正在尝试抓取页面中的信息。理想情况下,我希望将尽可能多的信息放入干净/易于阅读的 tsv 中,但要抓取的基本部分是:ID、名称、有机体、家庭、分类、UniProt ID、修改、序列和 PDB 结构 ID(例如在这种情况下,有一个 PDB 结构列表,第一个是 1BAS,最后一个是 4OEG)。

我在python3中写了这个:

import urllib.request
import sys
import pandas as pd
import bs4

out = open('pdb.parsed.txt', 'a')
for i in range(1000,1005):
#        try:
            url = 'http://isyslab.info/StraPep/show_detail.php?id=BP' + str(i)
            page = urllib.request.urlopen(url)
            soup = pd.read_html(page)
            print(soup)

我在这里附上了我的输出: 在此处输入图像描述

我有两个问题:

  1. 你可以看到我需要的一些信息丢失了(例如序列有 NaN)。

  2. 更重要的是,我看不到任何与 PDB ID 列表相关的字段?

如果可能,我希望使用 pd.read_html,因为过去我一直在使用 urllib/bs4,并且我发现在最近的抓取尝试中使用 pd.read_html 更成功。谁能解释我如何提取我需要的字段?

标签: pythonpandasbeautifulsoupurllib

解决方案


我相信您无法从某些行(例如“序列”行)中抓取条目,因为这些行是由 Javascript 填充的。对我有用的方法是结合使用 Selenium 和 Firefox 驱动程序来获取页面的 html 代码,然后使用 Beautiful Soup 来解析该代码。

以下是我如何能够为每个页面的 ID、名称、有机体、家庭、分类、UniProt ID、修改、序列和 PDB 结构 ID 抓取相关信息:

import urllib.request
import sys
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
import csv

pages = []
for page in range(1000,1005):
#        try:
    info_dict = {}
    url = 'http://isyslab.info/StraPep/show_detail.php?id=BP' + str(page)
    driver = webdriver.Firefox()
    driver.get(url)
    html = driver.page_source
    bs = BeautifulSoup(html, 'html.parser')
    main_table = bs.find('table', attrs={'class': 'main_table'})
    rows = main_table.findAll('tr')
    for row in rows:
        try: # We only want rows from a page where both row title and text are not null
            row_header = row.find('th').text
            row_text = row.find('td').text
        except:
            pass
        else:
            if row_header and row_text:
                if row_header in ['ID', 'Name', 'Organism', 'Family', 'Classification', 'UniProt ID']:
                    info_dict[row_header] = row_text
                elif row_header == 'Modification':
                    try: # Some pages have a null table entry for 'Modification'
                        mod_text = row.find('table').find('td').text
                    except:
                        pass
                    else:
                        if mod_text:
                            info_dict[row_header] = mod_text
                        else:
                            info_dict[row_header] = 'NA'
                # Pass 'Sequence' and 'Structure' as space separated strings
                elif row_header == 'Sequence':
                    seqs = ''
                    for i in row_text.split():
                        seqs += ' ' + i
                    info_dict[row_header] = seqs[1:]
                elif row_header == 'Structure':
                    pdb_ids = ''
                    a = row.find('tbody').find_all('a')
                    for i in a:
                        if i.text != '[x]': pdb_ids += ' ' + i.text
                    info_dict[row_header] = pdb_ids[1:]
    pages.append(info_dict)

keys = pages[0].keys()
with open('pdb.parsed.txt', 'a') as output_file:
    writer = csv.DictWriter(output_file, keys, delimiter='\t')
    writer.writeheader()
    writer.writerows(pages) # Add a tab-delimited row for each page we scraped

然后,如果需要,我可以读取刚刚创建为数据框的 .tsv 文件:

df = pd.read_csv('pdb.parsed.txt', delimiter='\t')

它看起来像这样: df

尽管包含较长字符串(例如 'Sequence')的列的内容被缩写,但我们可以验证整个序列确实存在:

df.iloc[0]['Sequence']

'PALPEDGGSG AFPPGHFKDP KRLYCKNGGF FLRIHPDGRV DGVREKSDPH IKLQLQAEER GVVSIKGVCA NRYLAMKEDG RLLASKCVTD ECFFFERLES NNYNTYRSRK YTSWYVALKR TGQYKLGSKT GPGQKAILFL PMSAKS'

保存的 tsv 文件的内容如下所示:

ID  Name    Organism    Family  Classification  UniProt ID  Modification    Sequence    Structure
BP1000  Fibroblast growth factor 2  Homo sapiens    heparin-binding growth factors family   Cytokine/Growth factor  FGF2_HUMAN  Phosphotyrosine; by TEC PALPEDGGSG AFPPGHFKDP KRLYCKNGGF FLRIHPDGRV DGVREKSDPH IKLQLQAEER GVVSIKGVCA NRYLAMKEDG RLLASKCVTD ECFFFERLES NNYNTYRSRK YTSWYVALKR TGQYKLGSKT GPGQKAILFL PMSAKS    1BAS 1BFB 1BFC 1BFF 1BFG 1BLA 1BLD 1CVS 1EV2 1FGA 1FQ9 1II4 1IIL 2BFH 2FGF 2M49 4FGF 4OEE 4OEF 4OEG
BP1001  Interleukin-2   Homo sapiens    IL-2 family Cytokine/Growth factor  IL2_HUMAN       APTSSSTKKT QLQLEHLLLD LQMILNGINN YKNPKLTRML TFKFYMPKKA TELKHLQCLE EELKPLEEVL NLAQSKNFHL RPRDLISNIN VIVLELKGSE TTFMCEYADE TATIVEFLNR WITFCQSIIS TLT  1IRL 1M47 1M48 1M49 1M4A 1M4B 1M4C 1NBP 1PW6 1PY2 1QVN 1Z92 2B5I 2ERJ 3INK 3QAZ 3QB1 4NEJ 4NEM
BP1002  Insulin Bos taurus  insulin family  Hormone INS_BOVIN       GIVEQCCASV CSLYQLENYC N 1APH 1BPH 1CPH 1DPH 1PID 2A3G 2BN1 2BN3 2INS 2ZP6 3W14 4BS3 4E7T 4E7U 4E7V 4I5Y 4I5Z 4IDW 4IHN 4M4F 4M4H 4M4I 4M4J 4M4L 4M4M
BP1003  Interleukin-1 beta  Homo sapiens    IL-1 family Cytokine/Growth factor  IL1B_HUMAN      APVRSLNCTL RDSQQKSLVM SGPYELKALH LQGQDMEQQV VFSMSFVQGE ESNDKIPVAL GLKEKNLYLS CVLKDDKPTL QLESVDPKNY PKKKMEKRFV FNKIEINNKL EFESAQFPNW YISTSQAENM PVFLGGTKGG QDITDFTMQF VSS    1HIB 1I1B 1IOB 1ITB 1L2H 1S0L 1T4Q 1TOO 1TP0 1TWE 1TWM 21BI 2I1B 2KH2 2NVH 31BI 3LTQ 3O4O 3POK 41BI 4DEP 4G6J 4G6M 4GAF 4GAI 4I1B 5BVP 5I1B 6I1B 7I1B 9ILB
BP1004  Lactoferricin-H Homo sapiens    transferrin family  Antimicrobial   TRFL_HUMAN      GRRRSVQWCA VSQPEATKCF QWQRNMRKVR GPPVSCIKRD SPIQCIQA    1Z6V 1XV4 1XV7 1Z6W 2GMC 2GMD

我使用以下 Anaconda 命令安装 Selenium,然后安装 Firefox 驱动程序:

conda install -c conda-forge selenium
conda install -c conda-forge geckodriver

推荐阅读