Python 搜索和抓取

Python Search and Scrape

我有一个问题,我想知道是否值得花时间尝试用 Python 来解决。我有一个很大的鱼类学名 CSV 文件。我想将该 CSV 文件与大型鱼类形态信息数据库 (www.fishbase.ca) 进行交叉引用,并将代码 return 设为每条鱼的最大长度。基本上,我需要创建代码来搜索 fishbase 网站上的每条鱼,然后在页面上找到最大长度信息,然后 return 在 CSV 文件中给我。最后两部分相对简单,但第一部分是我卡住的地方。提前致谢。

因此,为了在其他 Web 应用程序中使用这些信息,您需要使用 API 来获取他们的数据。

Fishbase.ca(或 .org)没有面向 public 的官方 API。有一些 chat in 2013 关于创建 RESTful API 这将是您需要的门票,但这还没有发生(不要屏住呼吸)。

另一种方法是使用您需要查找的鱼的名称,将其放入 URI(例如 www.fishbase.ca/fish/Rainbow+Trout),然后使用 Xquery 或类似工具向下钻取DOM求最大长度。

不幸的是,fishbase 也没有此方法所需的那种 URI,this 是虹鳟鱼的 URI - 使用 ID 而不是名称来轻松查找。

我建议寻找另一个数据提供者来寻找这两个 API 中的任何一个。

关于第二种方法:网站所有者可能不喜欢您以这种方式使用他们的网站。如果可以,请事先询问他们。

看起来你可以直接从属和种生成 url,即

虹鳟 (oncorhynchus mykiss) 变成

http://www.fishbase.ca/summary/Oncorhynchus-mykiss.html

类似

def make_url(genus, species):
    return (
        "http://www.fishbase.ca/summary/{}-{}.html"
        .format(genus.title(), species.lower())
    )

查看页面源代码,html 严重不符合语义;虽然用正则表达式解析 html 是邪恶和可怕的,但我真的认为这是这种情况下最简单的方法:

import re

fishlength = re.compile("max length : ([\d.]+) ([cm]{1,2})", re.I).search

def get_length_in_cm(html):
    m = fishlength(html)
    if m:     # match found
        value = float(m.group(1))
        unit  = m.group(2)
        if unit == "cm":
            return value
        elif unit == "m":
            return value * 100.
        else:
            raise ValueError("Unknown unit: {}".format(unit))
    else:
        raise ValueError("Length not found")

然后抓取每一页,

import csv
import requests
from time import sleep

DELAY = 2
GENUS_COL = 4
SPECIES_COL = 5

with open("fish.csv") as inf:
    next(inf)  # skip header row
    for row in csv.reader(inf):
        url  = make_url(row[GENUS_COL], row[SPECIES_COL])

        # should add error handling, in case
        #   that page doesn't exist
        html = requests.get(url).text

        length = get_length_in_cm(html)

        # now store the length value somewhere

        # be nice, don't pound their site
        sleep(DELAY)