【问题标题】:Debugging ScraperWiki scraper (producing spurious integer)调试 ScraperWiki scraper(产生虚假整数)
【发布时间】:2013-05-06 10:44:31
【问题描述】:

这是我在 ScraperWiki 上使用 Python 创建的刮板:

import lxml.html
import re
import scraperwiki

pattern = re.compile(r'\s')
html = scraperwiki.scrape("http://www.shanghairanking.com/ARWU2012.html")
root = lxml.html.fromstring(html)
for tr in root.cssselect("#UniversityRanking tr:not(:first-child)"):
    if len(tr.cssselect("td.ranking")) > 0 and len(tr.cssselect("td.rankingname")) > 0:
        data = {
            'arwu_rank'  : str(re.sub(pattern, r'', tr.cssselect("td.ranking")[0].text_content())),
            'university' : tr.cssselect("td.rankingname")[0].text_content().strip()
        }
    # DEBUG BEGIN
    if not type(data["arwu_rank"]) is str:
        print type(data["arwu_rank"])
        print data["arwu_rank"]
        print data["university"]
    # DEBUG END
    if "-" in data["arwu_rank"]:
        arwu_rank_bounds  = data["arwu_rank"].split("-")
        data["arwu_rank"] = int( ( float(arwu_rank_bounds[0]) + float(arwu_rank_bounds[1]) ) * 0.5 )
    if not type(data["arwu_rank"]) is int:
        data["arwu_rank"] = int(data["arwu_rank"])
    scraperwiki.sqlite.save(unique_keys=['university'], data=data)

它工作得很好,除非在抓取表格的最终数据行(“York University”行)时,而不是代码的第 9 行到第 11 行,导致字符串“401-500”从表并分配给data["arwu_rank"],这些行似乎反而导致int 450被分配给data["arwu_rank"]。您可以看到我添加了几行“调试”代码以更好地了解正在发生的事情,但调试代码并没有深入。

我有两个问题:

  1. 对于在 ScraperWiki 基础架构上运行的爬虫,我有哪些调试选项,例如解决此类问题?例如。有没有办法通过?
  2. 您能告诉我为什么将 int 450 而不是字符串“401-500”分配给“York University”行的 data["arwu_rank"] 吗?

编辑 2013 年 5 月 6 日 20:07 UTC

以下刮板完成没有问题,但我仍然不确定为什么第一个在“约克大学”行失败:

import lxml.html
import re
import scraperwiki

pattern = re.compile(r'\s')
html = scraperwiki.scrape("http://www.shanghairanking.com/ARWU2012.html")
root = lxml.html.fromstring(html)
for tr in root.cssselect("#UniversityRanking tr:not(:first-child)"):
    if len(tr.cssselect("td.ranking")) > 0 and len(tr.cssselect("td.rankingname")) > 0:
        data = {
            'arwu_rank'  : str(re.sub(pattern, r'', tr.cssselect("td.ranking")[0].text_content())),
            'university' : tr.cssselect("td.rankingname")[0].text_content().strip()
        }
        # DEBUG BEGIN
        if not type(data["arwu_rank"]) is str:
            print type(data["arwu_rank"])
            print data["arwu_rank"]
            print data["university"]
        # DEBUG END
        if "-" in data["arwu_rank"]:
            arwu_rank_bounds  = data["arwu_rank"].split("-")
            data["arwu_rank"] = int( ( float(arwu_rank_bounds[0]) + float(arwu_rank_bounds[1]) ) * 0.5 )
        if not type(data["arwu_rank"]) is int:
            data["arwu_rank"] = int(data["arwu_rank"])
        scraperwiki.sqlite.save(unique_keys=['university'], data=data)

【问题讨论】:

    标签: python screen-scraping scraperwiki


    【解决方案1】:

    在 ScraperWiki 上调试你的脚本没有简单的方法,不幸的是它只是将你的代码全部发送并返回结果,没有办法交互式地执行代码。

    我在您的代码副本中添加了更多打印,它看起来像在分配数据的位之前进行 if 检查

    if len(tr.cssselect("td.ranking")) > 0 and len(tr.cssselect("td.rankingname")) > 0:
    

    不会为“约克大学”触发,因此它将保持循环前一次的 int 值(您稍后设置)。

    【讨论】:

    • 感谢您提供有关调试的信息。不过,我不确定你的另一点。 IIUC,如果没有为约克大学行触发该条件,则永远不应为 data["university"] 分配值“约克大学”;然而在最后一次迭代中,data["university"]赋值为“York University”。
    • @sampablokuper 这可能是因为表格底部有一行文字“同一排名范围内的机构按字母顺序列出”。并且由于您不重置“数据”,它实际上会显示约克大学两次,第二次使用预先计算的值从前一次通过该循环运行。这有意义吗?
    • 没错。特别是,这是由于我在上面代码的第一个版本中使用的不正确的嵌套而发生的。谢谢:)
    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2018-12-17
    • 1970-01-01
    • 2013-03-11
    • 2017-03-19
    • 1970-01-01
    相关资源
    最近更新 更多