-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscraping_script.qmd
266 lines (191 loc) · 6.7 KB
/
scraping_script.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
---
title : "Scraper les communiqués de presse du secrétaire général des nations unies"
author: "Malo Jan"
format: pdf
---
```{r}
# Import packages
needs(tidyverse, rvest)
```
Principales fonctions d'`rvest` :
- `read_html()` : Extraction du code source d'une page HTML
- `html_element()` : Selection d'un élément sur cette page
- `html_text()` : Extraction du texte de cet élément
- `html_table()` : Extraction d'un tableau de cet élément
- `html_attr()` : Extraction d'un attribut de cet élément (ex : liens)
# Etape 1 : familiarisation avec le site web
- [Communiqués de presse du secrétaire général des nations unies](https://press.un.org/en/content/secretary-general/press-release)
# Etape 2 : extraction du contenu d'une seule page web
```{r}
# Création d'une url d'un communiqué
url_test <- "https://press.un.org/en/2023/sgsm22043.doc.htm"
# Extraction du code html de la page
(page_html <- read_html(url_test))
# Extraction du titre du communiqué
(title <- page_html %>%
html_element(".page-header") %>%
html_text())
# Extraction du texte du communiqué
(text <- page_html %>%
html_element(".field--type-text-with-summary") %>%
html_text())
# Extraction de la date du communiqué
(date <- page_html %>%
html_element("time") %>%
html_text())
# Extraction des keywords
(keywords <- page_html %>%
html_elements(".field__items a") %>%
html_text() |>
str_c(collapse = "|"))
(id <- page_html |>
html_element(".field--name-field-symbol") |>
html_text())
un_pr <- tibble(title, text, date, keywords, id)
```
## Etape 3 : extraction des urls de tous les communiqués
```{r}
ex_urls <- "https://press.un.org/en/content/secretary-general/press-release" |>
read_html() |>
html_elements("h3 > a") |>
html_attr("href")
ex_urls <- str_c("https://press.un.org", ex_urls)
ex_urls
```
- Souvent, on veut plus d'une url (et là, c'est là que commence le fun et la beauté de l'automatisation !)
- Les urls sont parfois structurées de façon logique ce qui rend l'extraction facile
- https://press.un.org/en/content/secretary-general/press-release?page=1
- https://press.un.org/en/content/secretary-general/press-release?page=2
- https://press.un.org/en/content/secretary-general/press-release?page=3
- Dans ce cas, le workflow consiste à :
- Identifier toutes les urls des pages où il y a des communiqués de presse
- Pour chacune de ces pages, collecter les urls des communiqués de presses
- Pour chaque communiqué de presse : extraire le titre, l'auteur, la date et le texte
```{r}
urls <- str_c("https://press.un.org/en/content/secretary-general/press-release?page=", 1:1936)
# Fonction pour collecter les urls des communiqués de presse
collect_urls <- function(x) {
page <- read_html(x)
urls <- tibble(
link = page |>
html_elements("h3 > a") |>
html_attr("href")
) |>
mutate(link = str_c("https://press.un.org", link))
}
# Test sur 10 pages
pr_links <- map_df(urls, collect_urls, .progress = T)
write_csv(pr_links, "data/pr_links.csv")
```
# Etape 4 : Collecter le texte de chaque communiqué de presse
```{r}
# Write a function to scrap everything
(title <- page_html %>%
html_element(".page-header") %>%
html_text())
# Extraction du texte du communiqué
(text <- page_html %>%
html_element(".field--type-text-with-summary") %>%
html_text())
# Extraction de la date du communiqué
(date <- page_html %>%
html_element("time") %>%
html_text())
# Extraction des keywords
(keywords <- page_html %>%
html_elements(".field__items a") %>%
html_text() |>
str_c(collapse = "|"))
(id <- page_html |>
html_element(".field--name-field-symbol") |>
html_text())
collect_content <- function(x) {
# Get html code of page
page <- read_html(x)
# Create dataframe with the different elements
tibble(
# Extract title
title = html_element(page, ".page-header") |>
html_text(),
text = html_element(page, ".field--type-text-with-summary") |>
html_text(),
date = html_element(page, "time") |>
html_text() |>
dmy(),
keywords = html_elements(page, ".field__items a") |>
html_text() |>
str_c(collapse = "|"),
id = html_element(page, ".field--name-field-symbol") |>
html_text())
}
# Apply this function to all of the press releases urls
(cp <- map(pr_links$link, safely(collect_content), .progress = T))
cp_df <- cp |>
map_df("result")
cp_df <- cp_df |>
mutate(year = str_sub(date, 1, 4) |> as.numeric(),
secretary_general = case_when(
date >= "2017-01-01" ~ "Antonio Guterres",
date >= "2007-01-01" ~ "Ban Ki-Moon",
date >= "1997-01-01" ~ "Kofi Annan",
date >= "1992-01-01" ~ "Boutros Boutros-Ghali"))
# Write the dataframe to a csv file
# write_csv(cp_df, "data/cp_df.csv")
# If you run this for all the 19354 press releases, it will take several hours
```
# Etape 6 : Explorer les données
```{r}
cp_df <- read_csv("data/cp_df_all.csv")
# Evolution du nombre de communiqués de presse par année et par secrétaire général
cp_df |>
ggplot(aes(date, fill = secretary_general)) +
geom_histogram(bins =25) +
scale_fill_viridis_d() +
theme_minimal()
```
```{r}
# Exploring keywords
cp_df |>
separate_rows(keywords, sep = "\\|") |>
count(keywords) |>
filter(keywords != "") |>
arrange(desc(n))
cp_df |>
separate_rows(keywords, sep = "\\|") |>
count(keywords) |>
filter(keywords != "") |>
arrange(desc(n)) |>
filter(n > 100) |>
mutate(keywords = fct_reorder(keywords, n)) |>
ggplot(aes(keywords, n)) +
geom_col() +
coord_flip() +
theme_minimal()
ggsave("figures/unsg_keywords.png", width = 10, height = 6, dpi = 300)
```
```{r}
# Keyword search
cp_df <- cp_df |>
mutate(
climate = str_detect(text, "climate change|global warming|greenhouse gas|carbon dioxide|CO2 emissions|climate action|climate crisis|climate emergency|climate catastrophe|climate disaster|climate chaos"),
)
climate_shares <- cp_df |>
group_by(year) |>
count(climate) |>
mutate(prop = n / sum(n)) |>
filter(climate == TRUE)
climate_shares |>
ggplot(aes(x = year, y = prop)) +
geom_point() +
geom_line() +
scale_y_continuous("Press releases mentioning climate change", labels = scales::percent) +
scale_x_continuous("Year") +
theme_minimal() +
labs(caption = "Data : UNSG press releases")
ggsave("figures/climate_shares.png", width = 10, height = 6, dpi = 300)
```
```{r}
cp_df |>
filter(climate == TRUE, year == 2006) |>
view()
```