第一个python脚本,刮板,建议欢迎

时间:2011-04-12 10:03:56

标签: python mechanize lxml scraper

我刚刚完成了我的第一个python脚本,一个来自philipines的选举数据的刮刀。我没有编程背景,我已经使用stata进行统计分析,最近在R中考虑了一点,因为我想在某些时候切换。但我想学习python从网站和其他来源提取数据。到目前为止,我只浏览了python教程,O'Reilly的“学习Python”正在等待我的架子。我通过从其他人的脚本中获取灵感并浏览包含的包文档来编写以下脚本。

我基本上寻找的是一般建议。该脚本确实有效,但是有多余的部分吗?我应该采用不同的结构吗?是否有任何典型的(或简单的愚蠢)初学者错误?

我自己编写了一些我在剧本后面列出的问题。

import mechanize
import lxml.html
import csv

site = "http://www.comelec.gov.ph/results/2004natl/2004electionresults_local.aspx"

br = mechanize.Browser()
response = br.open(site)

output = csv.writer(file(r'output.csv','wb'))


br.select_form(name="ctl00")
provinces = br.possible_items("provlist")

for prov in provinces:
    br.select_form(name="ctl00")
    br["provlist"] = [prov]
    response = br.submit()
    br.select_form(name="ctl00")
    pname = str(br.get_value_by_label("provlist")).strip("[]")
    municipalities = br.possible_items("munlist")
    for mun in municipalities:
        br.select_form(name="ctl00")
        br["munlist"] = [mun]
        response = br.submit(type="submit", name="ctl01")
        html = response.read()
        root = lxml.html.fromstring(html)
        try: 
            table = root.get_element_by_id(id="dlistCandidates")
            data = [
                       [td.text_content().strip() for td in row.findall("td")] 
                       for row in table.findall('tr')
                   ]
        except KeyError:
            print "Results not available yet."
            data = [ [ "." for i in range(5) ] ]
        br.select_form(name="ctl00")
        mname = str(br.get_value_by_label("munlist")).strip('[]')
        print pname, mname, data, "\n"
        for row in data:
            if row: 
                row.append(pname)
                row.append(mname)
                output.writerow([s.encode('utf8') if type(s) is unicode else s for s in row])
  1. 当我执行脚本时,我收到一条错误消息“DeprecationWarning:[item.name for item.in self.items]。原因是什么,我应该担心吗?

  2. 我现在循环遍历各省的数字键,然后每次都获取名称。我是否应该在开头建立一个字典然后循环呢?

  3. 是否有一种简单的方法可以将“ene”字符(上面的波形符号为N)直接编码为正常N?

  4. 每次更换“数据”时,我最好如何收集所有内容,然后在最后写一个csv文件?这会是一个更好的解决方案吗?

  5. 该网站需要很长时间才能回复每个请求。获取所有数据大约需要一个小时。我可以通过执行几个脚本并连接省份列表来加快速度。我如何在一个脚本中发送并行请求?我最终希望从该站点获得更多数据,并且加速这个过程会很不错。

  6. 我已经尝试过BeautifulSoup和lxml模块,但更喜欢lxml解决方案。哪些其他模块通常对这些任务有用?

  7. 内置模块和其他模块的文档/帮助文件是否有任何中央寄存器?在我看来,到处都是散布的文件,这有点不方便。写帮助(某事)通常会导致“找不到的东西”。

  8. 非常感谢任何建议和批评。英语不是我的母语,但我希望我能设法将错误保持在最低限度。

1 个答案:

答案 0 :(得分:6)

  1. DeprecationWarning来自mechanize模块,并在您致电possible_items时发出。这表明有更好的方法来获得相同的效果。我不知道为什么作者没有更明确地说明这一点。

  2. 我认为这没什么区别。

  3. 您可能需要查看http://effbot.org/zone/unicode-convert.htm

  4. 正如你所做的那样逐步写作对我来说很好看。你可以改为创建一个行列表,在循环中追加它,然后在最后一次写出整个行;主要优点是模块化略有增加。 (假设您想要进行相同的抓取,但以另一种方式使用结果;您可以更轻松地重用代码。)

  5. (a)如果远程站点需要很长时间才能响应并且您的所有抓取都来自该远程站点,您确定并行处理多个请求实际上会有所帮助吗? (b)您可能想要检查相关网站的所有者是否反对这种抓取,既不是出于礼貌,也是因为如果他们反对,那么他们可能会注意到您正在做的事情并阻止您。我猜这是因为它是一个政府网站,他们可能还可以。 (c)查看Python标准库中的threadingmultiprocessing模块。

  6. 我不知道;遗憾。

  7. 没有。 (除非你算上谷歌。)

  8. 看起来好像你做了一些来回确定省和市。如果他们不在脚本的调用之间进行更改,则可能值得将它们保存在本地某处,而不是每次都询问远程网站。 (获得的收益可能不值得 - 但您可能想要衡量获取该信息所需的时间。)

    您可以考虑将将一大块HTML转换为候选列表(如果它就是这样)的代码提取到一个单独的函数中。

    您可以考虑将这样的内容提取到单独的函数中:

    def select_item(br, form, listname, value, submit_form=None):
      br.select_form(form)
      br[listname] = [value]
      return br.submit(type="submit", name=(submit_form or form))
    

    也许是这样的:

    def get_name(br, formname, label):
    br.select_form(formname)
      return str(br.get_value_by_label(label)).strip("[]")