美国参议院里的合作网络

这是《基于R语言自动收集》这本书的第十二章 ,因为网页已经改变源代码也发生了改变。所以重新整理了代码分享。

美国国会的法案存放在一个相对容易访问的数据库里,地址是:https://www.congress.gov。我们的网络抓取练习的第一步是对数据存放的方式进行检查。为了追踪抓取程序。我们可以

(1)  打开https://www.congress.gov

(2)    转到“Legislation”。

(3)    点击页面里的“Congress”,在“Congress”的子目录下点击“111(2009--2010)”。

(4)    点击页面里的“Chamber of Origin”,在“Chamber of Origin”的子目录下点击“Senate”。

按法案编号升序排列后,第111届国会期间提出的4059条法案包含在显示的连续页面中,每个页面显示100条信息。我们可以看到每条提出法案的标题、提案人、共同提案人数量和最后一次针对该法案的主要行动。点击进入第一条法案S.1的页面可以发现有十七位Cosponsors(共同提案人)。让该页面显示17位共同提案人的列表,此时页面包含我们所需的全部信息。观察该页面的URL:https://www.congress.gov/bill/111th-congress/senate-bill/1/cosponsors?r=1。我们可以看到这份提案的序号1是在国会届数111后面的,为了确认这个规律,我们查看第二个法案的URL,可以看到国会届数111后面的提案序号变为了2。选择一个随机数,如66,我们就可以手工改写原始URL

https://www.congress.gov/bill/111th-congress/senate-bill/66/cosponsors?r=66果然灵验了。现在,根据网络抓取良好实践里的规则,我们要把所有4059条法案的网页下载到硬盘,并尝试在第二步读取它们。

1.2下载网页

我们通过下载安装包并加载本练习后续部分需要用到的某些组件来启动R会话。

扫描二维码关注公众号,回复: 2801059 查看本文章

下载安装整个操作所需要的包

> install.packages("RCurl")

> install.packages("XML")

> install.packages("httr")

> install.packages("stringr")

> install.packages("igraph")

加载安装包

> library(RCurl)

> library(XML)

> library(httr)

> library(stringr)

> library(igraph)

    我们设置的抓取函数由3个简单步骤组成,即为每个法案创建一个唯一的URL,下载网页,并最终把页面作为HTML文件写到本地文件夹Bills_111里。我们还加入了一个简单的进度指示器,用于监控下载过程。

创建一个空文件夹用来存储下载的html文件

> dir.create("Bills_111/")

利用url的规律用for循环下载保存4059个页面

> for(i in 1:4059){

url<-str_c("https://www.congress.gov/bill/111th-congress/senate-bill/i/cosponsors?r=i")

bill.result <- getURL(url) # 开始下载网页

write( bill.result,str_c("Bills_111/Bill_111_S", i,  ".html" ) )

# 把网页写入到本地文件夹,存储

cat(i, "\n")# 显示进度

}

首先以S1提案为例解析整个网页

>html.source<-htmlParse(file="Bills_111/Bill_111_S1.html")

根据源代码中,所有提案议员都在标签<td>…</td>中,且都有Sen的身份标志,确定path的内容,接下来调用xpathSApply函数提取整个页面的议员。

> all_sen<-xpathSApply(html.source, path ="//td/a[contains(text(),'Sen')]", xmlValue)

查看all_sen的内容

 

如上图所示提取了此页面的18名议员的姓名,按照规律,第一个是主提案人,剩下的是共同提案人。

> sponsor<-all_sen[1]

> cosponsors<-all_sen[-1]

> cosponsors[1:3]

[1] "Sen. Begich, Mark [D-AK]*"   "Sen. Bingaman, Jeff [D-NM]*"

[3] "Sen. Boxer, Barbara [D-CA]*"

> length(cosponsors)

[1] 17

> cleanUp<-function(x){

 name<-sub("[[:alpha:]*[:punct:]*]+$","",x)

 name<-str_trim(str_replace(name,"Sen.",""))

 return(name)}

对前面的结果运用cleanUp( )函数,可以得到:

> cleanUp(sponsor)

[1] "Reid, Harry"

> cleanUp(cosponsors)

 [1]"Begich, Mark"           "Bingaman, Jeff"         

 [3]"Boxer, Barbara"         "Brown, Sherrod"        

 [5]"Casey, Robert P., Jr."  "Clinton, Hillary Rodham"

 [7]"Durbin, Richard J."     "Kennedy, Edward M."    

 [9]"Kerry, John F."         "Klobuchar, Amy"        

[11] "Lautenberg, Frank R."    "Levin, Carl"           

[13] "Lieberman, Joseph I."    "McCaskill, Claire"     

[15] "Menendez, Robert"        "Schumer, Charles E."   

[17] "Stabenow, Debbie" 

用for循环收集4059个案例中所有的提案议员

> sponsor.list <- list()

> for(i in 1:4059) {

 file<-str_c("Bills_111/Bill_111_S",i, ".html")

 html_source<-htmlParse(file)

 all_sen<-xpathSApply(html_source, path ="//body/div//td/a[contains(text(),'Sen')]",         xmlValue)

 sponsor<-cleanUp(all_sen[1])

 cosponsors<-cleanUp(all_sen[-1])

#把结果放到sponsor list

sponsor.list[[str_c("S.", i)]] <-list(sponsor = sponsor, cosponsors = cosponsors)

}

创建议员法案关系矩阵

> all.senators <- unlist(sponsor.list)#把列表展开

> all.senators <- unique(all.senators)#去除重复值

> all.senators <- sort(all.senators)#按照一定的顺序进行排列

> head(all.senators)#查看部分议员信息

[1] "Akaka, Daniel"    "Alexander, Lamar""Barrasso, John" 

[4] "Baucus, Max"      "Bayh, Evan"       "Begich, Mark"  

> sponsor.matrix <- matrix(NA, nrow = 4059, ncol= length(all.senators))

> colnames(sponsor.matrix) <- all.senators

> rownames(sponsor.matrix) <-paste("S.", seq(1, 1000), sep ="")

最后,对提案人列表进行迭代,填充到正确的单元格里。

> for(i in 1:length(sponsor.list)){

sponsor.matrix[i,which(all.senators == sponsor.list[[i]]$sponsor)] <- "Sponsor"

if(length(sponsor.list[[i]]$cosponsors)> 0){

for(j in1:length(sponsor.list[[i]]$cosponsors)){

sponsor.matrix[i,which(all.senators == sponsor.list[[i]]$cosponsors[j])]<-"Cosponsor"

        }

     }

 }

查看矩阵30到35行的信息

> sponsor.matrix[30:35,31:34]

     Cornyn,John Crapo, Mike DeMint, Jim Dodd, Christopher

S.30 NA          NA          NA          NA              

S.31 NA          NA          NA          NA              

S.32 NA          NA          NA          NA              

S.33 NA          NA          NA          NA              

S.34 "Cosponsor"  "Cosponsor""Sponsor"       NA              

S.35 "Cosponsor"   NA         NA          NA 

到这里就算是一个比较完美的结果,换成表格就是:

接下来,我们要设置一个议员关于提案的数据矩阵,我们想要的数据结构如下

 

参议员A

参议员B

参议员C

……

S.1

共同提案人

提案人

共同提案人

……

S.2

 

共同提案人

 

……

S.3

 

 

提案人

……

……

……

……

……

剩下还有两节的内容会整理到期末作业,跟书上代码差别不大,就不赘述了。不过修改了这个代码以后,我就是我们班可以凭借for循环和list走天下的人了哈哈哈哈....

猜你喜欢

转载自blog.csdn.net/never0822/article/details/80926339