用python和/或scrapy刮掉ajax网页

时间:2012-11-27 15:46:34

标签: python ajax web-scraping scrapy

我想做什么是在petitions.whitehouse.gov上的一个或多个请愿书中删除请愿数据 - 姓名,城市,州,日期,签名号码

我认为此时python是可行的方法 - 可能是scrapy库 - 以及一些处理网站ajax方面的功能。这个刮刀的原因是这个请愿数据不向公众开放。

我是一名自由科技记者,我希望能够将每份请愿书的数据转储成CSV文件,以便分析每个州签署州请愿书的人数,以及来自多个请愿书的数据,查找签署多个请愿书的人数等,然后对请愿程序和数据本身的政治可行性做出一些结论。

petitions.whitehouse.gov上的请愿功能作为Drupal模块运行,白宫开发人员在github https://github.com/WhiteHouse/petition/issues/44上回复了我的问题请求,他们正在开发一个API,允许访问来自的请愿数据模块。但该API没有发布日期;而且这并没有解决目前petitions.whitehouse.gov上的请愿数据问题。

我已通过电子邮件向白宫和白宫开发人员发送电子邮件,声称我是一名自由撰稿人,并要求以某种方式访问​​数据。白宫数字战略办公室告诉我,“不幸的是,我们目前没有办法提供数据导出,但我们正在努力通过API开辟数据。” 白宫有一项“开放数据”倡议,但显然请愿数据未被涵盖。

隐私权和服务条款:签署请愿书时预计隐私很少。没有明确的服务条款可以解决网络抓取这些数据的问题。

做了什么: UNC的一些教师编写了(我假设的)一个python脚本来抓取数据,但是他们不想向我发布脚本,说他们仍在努力。 http://www.unc.edu/~ncaren/secessionists/他们确实向我发送了一份我特别感兴趣的请愿书的CSV数据转储。

我做了什么:我为此设置了一个github项目,因为我希望任何请愿数据抓取器对每个人都有用 - 请愿者本人,记者等 - 谁想要能够获得这些数据。 https://github.com/markratledge/whitehousescraper

我没有使用python的经验,也没有使用shell脚本的经验,而我正在尝试做的事情显然超出了我的经验。

我运行了一个GUI脚本,每五秒左右向Web浏览器发送一个“空格键”,这样就可以通过将浏览器文本剪切并粘贴到文本编辑器中来删除~10,000个签名。从那里,我可以使用grep和awk将文本处理成CSV格式。当然,这不太顺利; Chrome因页面大小而陷入困境,需要花费数小时才能获得这么多签名。

到目前为止我发现了什么:从我从其他SO问题和答案中收集到的内容,看起来Python和scrapy http://scrapy.org是避免问题的方法浏览器。但该页面使用ajax函数来加载下一组签名。看来这是一个“静态”的ajax请求,因为URL没有改变。

在Firebug中,JSON请求标头似乎附加了一个随机字符串,前面有一个页码。这对于需要做什么有什么意义吗?脚本是否需要模拟并将其发送到Web服务器?

  

请求   网址:https://petitions.whitehouse.gov/signatures/more/50ab2aa8eab72abc4a000020/2/50b32771ee140f072e000001   请求   网址:https://petitions.whitehouse.gov/signatures/more/50ab2aa8eab72abc4a000020/3/50b1040f6ce61c837e000006   请求   的URL:https://petitions.whitehouse.gov/signatures/more/50ab2aa8eab72abc4a000020/4/50afb3d7c988d47504000004

这是在页面上加载签名的JS函数:

(function ($) {
Drupal.behaviors.morePetitions = {
  attach: function(context) {
    $('.petition-list .show-more-petitions-bar').unbind();
    $(".petition-list .show-more-petitions-bar").bind('click',
      function () {
        $('.show-more-petitions-bar').addClass('display-none');
        $('.loading-more-petitions-bar').removeClass('display-none');

        var petition_sort = retrieveSort();
        var petition_cols = retrieveCols();
        var petition_issues = retrieveIssues();
        var petition_search = retrieveSearch();
        var petition_page = parseInt($('#page-num').html());

        var url = "/petitions/more/"+petition_sort+"/"+(petition_page + 1)+"/"+petition_cols+"/"+petition_issues+"/"+petition_search+"/";
        var params = {};
        $.getJSON(url, params, function(data) {
          $('#petition-bars').remove();
          $('.loading-more-petitions-bar').addClass('display-none');
          $('.show-more-petitions-bar').removeClass('display-none');
          $(".petition-list .petitions").append(data.markup).show();

          if (typeof wh_petition_adjustHeight == 'function') {
            wh_petition_adjustHeight();
          }

          Drupal.attachBehaviors('.petition-list .show-more-petitions-bar');
          if (typeof wh_petition_page_update_links == 'function') {
            wh_petition_page_update_links();
          }
        });

        return false;
      }
    );
  }
}

当滚动到浏览器窗口底部时显示此div时会触发:

<a href="/petition/.../l76dWhwN?page=2&amp;last=50b3d98e7043012b24000011" class="load-next no-follow active" rel="509ec31cadfd958d58000005">Load Next 20 Signatures</a>
<div id="last-signature-id" class="display-none">50b3d98e7043012b24000011</div>

那么,最好的方法是什么?我在哪里使用scrapy?还是有另一个python库更适合这个吗?

随意发表评论,指出我的代码剪辑方向,其他SO问题/答案,贡献给github。我想要做的事情显然超出了我的经验。

2 个答案:

答案 0 :(得分:1)

“随机链接”看起来像是:

https://petitions.whitehouse.gov/signatures/more/ petitionid / pagenum / lastpetition 其中 petitionid 对于单个请愿是静态的, pagenum 每次递增,并且每次从请求返回 lastpetition

我通常的做法是使用请求库来模拟cookie的会话,然后确定浏览器的请求。

import requests
s=requests.session()
url='http://httpbin.org/get'
params = {'cat':'Persian',
          'age':3,
          'name':'Furball'}             
s.get(url, params=params)

我会特别注意以下链接:

<a href="/petition/shut-down-tar-sands-project-utah-it-begins-and-reject-keystone-xl-pipeline/H1MQJGMW?page=2&amp;last=50b5a1f9ee140f227a00000b" class="load-next no-follow active" rel="50ae9207eab72aed25000003">Load Next 20 Signatures</a>

答案 1 :(得分:0)

使用Python完全模拟Jquery / Javascript很难。 You could have a look on spidermonkey 或者像Selenium这样的网络测试自动化工具,可以完全自动化任何浏览器操作。 关于SO的上一个问题: How can Python work with javascript