Lecture 2: Text Processing, Web Scraping and Text Mining



Yanfei Kang
yanfeikang@buaa.edu.cn

School of Economics and Management
Beihang University

In this lecture we are going to learn …

Packages required in this lecture

install.packages(c("stringr", "rvest", "knitr", "jiebaR", "wordcloud2", "tm", 
"slam" , "proxy", "topicmodels", "RColorBrewer"))



Text Processing

Read and write text data into R

# read text data into R
# WMTnews.txt can be found on my Github.
wmt.news <- readLines('WMTnews.txt')
# You can also read from the file I put online. It takes roughly 2 mins to read.
# wmt.news <- readLines("https://yanfei.site/docs/dpsa/WMTnews.txt",
#                       encoding = 'UTF-8') 
length(wmt.news)
## [1] 449
# print the first news article without quotes
noquote(wmt.news[1])
## [1] 沃尔玛在中国强推综合工时制,引发多地门店员工罢工由于不满沃尔玛近期在中国推行的“综合工时制”改革,从7月1日开始,沃尔玛多地门店的基层员工发起罢工。据江西南昌当地媒体的报道,近日南昌沃尔玛八一广场店成了“闹市”,这里的沃尔玛员工正在集体罢工,工装背后贴着的A4纸上写着“沃尔玛员工站起来,抵制综合工时制度,反对欺骗,坚决维权。”据悉,之所以会发生这样的事,是因为沃尔玛要实行新的薪酬制度。员工称,他们本来是与沃尔玛签订了长期劳动合同,现在沃尔玛要求更改合同,本来的月薪制更改成小时制,并强制让员工签字。在大家看来,用工合同的更改,意味着他们的保障得到了根本性的改变。不仅如此,这些员工称,新的合同也变相提高了基本工资,从而规避城市基本工资上调政策,变相降低总体工资。除南昌外,成都、重庆、深圳、哈尔滨的个别商场员工也组织了罢工,以抗议这一次的“综合工时制”改革。由沃尔玛员工自发组织的中国员工联谊会介绍,此前沃尔玛在中国一直以来采用的是标准工时制,全职工每天工作8小时,每周工作5天,每周40小时;但沃尔玛自今年5月开始在中国各地分店推行综合计算工时工作制。新规则下,全职工每天工作4-11小时,每周工作3-6天,每周20-66小时,每月平均标准工时174小时、加班工时不超过36小时。沃尔玛员工认为,新规则可能导致工作时间安排不稳定,而且单方面实施新工时制度在程序上是违法的。知情人士告诉澎湃新闻,沃尔玛在美国实行的就是综合工时制,在中国推行这一改革也是为了与总部统一标准。在中国,综合工时制符合法律要求。《劳动法》共规定三种工时计算标准,即标准工时制、综合工时制和不定时工时制。标准工时制和综合工时制的区别在于,标准工时制以“天”为计算单位,而综合工时制以“周、月、年”为计算单位。也就是说,标准工时制是按照社会上最常见的8小时工作制,每周不超过40小时的标准来计算员工的工作量。而综合工时制是在每周不超过40小时的工作总量下,灵活分配每天的工作时间,工作长度。只是,从标准工时制改为综合工时制,还需要得到中国各地相关劳动主管部门的批准,而各地的要求也不尽相同。有的地方主管部门直接批准即可执行;有的地方主管部门则要求获得绝大部分员工的同意才可推行新政。因此,沃尔玛一些城市门店的基层员工需要签字同意这一改革。在这一过程中,部分员工对新政有各种各样的担忧,罢工事件由此爆发,沃尔玛在中国的“综合工时制”改革遭遇强大的挑战。据江西当地电视台7月3日报道,南昌市总工会的领导已经要求沃尔玛华中地区负责人向沃尔玛中国总部反映,恢复标准工时制。截止澎湃新闻发稿之时,尚未获得沃尔玛中国总部针对这一事件的回应。业内分析,沃尔玛在中国推行“综合工时制”改革的目的还是为了降低人力成本。沃尔玛这两年来一直在“做减法”,减去他们认为不利于管控、不利于标准化、不利于规模化、不利于降低成本的任何环节、商品、配置等。这种做法的好处在于,沃尔玛进一步加强中央管控,门店更加“听话”,并且可以节省成本,在利润上有直接体现。但这种做法也存在门店的本地化、个性化日益下降,商品竞争力逐渐下滑的弊端。(来源:澎湃新闻)进入【新浪财经股吧】讨论
# write text data into R
cat(wmt.news, file = "WMTnews.txt", sep = "\n")

Length of each article

# number of characters in each news article
nchar(wmt.news)
##   [1] 1308 1005 1066 2886  440  270 2313  452 3099  683 3119 3140  397 2781
##  [15]  419  460 2839 2519 2934  572 1181  156 1723 3301 2245 2401 2872 2849
##  [29] 1226 2048 2324 3439 3182 1055 1698 1881  673 2877 1719  254 2342  770
##  [43] 1325  771 1923  497 3145  139 2096  323  251 1652  495  301 1227  419
##  [57] 1720 3219  736 3245 2602  722 1345  748  524 1537  924   62   54  632
##  [71] 3143 3120  966 1790  962  940 2636 1497  964  250  218  338 1677  346
##  [85]  366 1679  841 2011  866 1314  393  664 1708 1320 1977 1592  285  833
##  [99]  731  336 1882 3241 2270 1251 1455  215 2264  345  344  955  782  267
## [113]  411    0  683  158  285 1155  168  382 1759 5446  292  651 3927  578
## [127]  607  144  142  540  867 1136 1874  654  539  141   42 1033  229  140
## [141] 1246  892 1442  863 2293  289 2583  142  564  773  694  121  122 1958
## [155] 1251 1284  928 2195  493 1334 2537 1724 1229  728 1552  548 3479  763
## [169] 1907    0  789  997  626  797  855  560  882 1166   48  552   52  729
## [183]  248  701  624  632  751  356  542  346 1054 2617  237 3197  582  827
## [197] 1366  491 1016  538  956 3938  963 1188    0 2352 1176 1247 2533 1249
## [211] 2039 1426  463  456 1042  128  551 1589  296  468 3950  198  855  870
## [225]  254  660  207  599  362  430  442  285  843  735 5897  308  149  300
## [239]  598  592  399  835 2299  866  840  211  379  397 1415  456  945  439
## [253] 1485  995  242 2253  239  399  879 1630  690  825  740  201  300   71
## [267]   52 1246  653  998  554 1623 1134 1138 1066  360  302  709  828  159
## [281]  598  170  420  432 3448  513  292 3305  136 1883 2184  794  534  782
## [295] 1919 1527 1562 1638  811    0  931  576 1168 1218 2130  798  291  465
## [309]  720 4068  563 1806   90   25 1014   72 1496  468    0 1571 1769 2775
## [323]  972 3515 1898  181 1263  376   92 1903  138    0  410 2128  465  575
## [337] 1740  583  856  879 1214  398 1084 1114 2146  341 2159  480 1952  469
## [351] 1127  113   95 2922  132  872 5488  205  137  145  706  469  470 1095
## [365]  231 1093 1068  950  650  205  887  380   25 1297 1642  821 3251  830
## [379] 2028    0  522  146  347  560  598  662  400  218 1965 1627 1551  235
## [393]  182  777  534 1048 7061  414  167 2986 1214  425 1107 1138 1229 1186
## [407] 1216    0  727 1758  773 2073  588  864  299  415    0 3256  741 3691
## [421]  403 1979 2050    0    0  661 1458 1231 1445  814  799 2477 1920 1493
## [435]  166  554  114  711 1456 2669    0 1183 1123  209 1527  115  297 1425
## [449]  576
# library(stringr); str_length(wmt.news)

Concatenate strings

Concatenate two strings

# concatenate characters 
paste('2015', '06-04', sep = '-')
## [1] "2015-06-04"
paste('2015', c('06-04', '06-05'), sep = '-')
## [1] "2015-06-04" "2015-06-05"
paste('2015', c('06-04', '06-05'), sep = '-', collapse = ' ')
## [1] "2015-06-04 2015-06-05"
# str_c() in stringr
library(stringr)
str_c('2015', '06-04', '00:00', sep = '-')
## [1] "2015-06-04-00:00"
# frequently used in web scraping
paste('http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=', 
      '阿里巴巴', sep = '')
## [1] "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=北京&kw=阿里巴巴"
paste('http://sou.zhaopin.com/jobs/searchresult.ashx?jl=', 
      '上海', '&kw=', '阿里巴巴', sep = '')
## [1] "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=上海&kw=阿里巴巴"

Combine text and variable values

# combine text and variable values
comp <- '阿里巴巴'
job.location <- '上海'
sprintf('http://sou.zhaopin.com/jobs/searchresult.ashx?jl=%s&kw=%s',
        job.location, comp)
## [1] "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=上海&kw=阿里巴巴"

Split strings

# split characters
dates <- c('2015-06-04', '2015-06-05')
strsplit(dates, "-")
## [[1]]
## [1] "2015" "06"   "04"  
## 
## [[2]]
## [1] "2015" "06"   "05"
strsplit('2015-06-04', '-')
## [[1]]
## [1] "2015" "06"   "04"
# another way
library(stringr)
str_split(dates, '-')
## [[1]]
## [1] "2015" "06"   "04"  
## 
## [[2]]
## [1] "2015" "06"   "05"
str_split('2015-06-04', '-')
## [[1]]
## [1] "2015" "06"   "04"

Pattern Matching

# search for matches
mySentences <- c('沃尔玛还与微信跨界合作,顾客可通过沃尔玛微信服务号的付款功能在实体门店秒付买单。', 
                 '沃尔玛移动支付应用已经部署在其全美4,600家超市中。')
grep('沃尔玛', mySentences)
## [1] 1 2
grepl('沃尔玛', mySentences)
## [1] TRUE TRUE
library(stringr); str_detect(mySentences, '沃尔玛')
## [1] TRUE TRUE
regexpr('沃尔玛', mySentences)
## [1] 1 1
## attr(,"match.length")
## [1] 3 3
gregexpr('沃尔玛', mySentences)
## [[1]]
## [1]  1 18
## attr(,"match.length")
## [1] 3 3
## 
## [[2]]
## [1] 1
## attr(,"match.length")
## [1] 3

Pattern Replacement

# replace white spaces 
messySentences <- c('沃尔玛还与微信   跨界合作,顾客可通过沃尔玛微信服务号的付   款功能在实体门店秒付买单。', 
                    '沃尔玛移动支付应 用已经部  署在其全美4,600家超市中。')

# patten replacement
# sub(pattern, replacement, x, ...)
sub(' ', '', messySentences)
## [1] "沃尔玛还与微信  跨界合作,顾客可通过沃尔玛微信服务号的付   款功能在实体门店秒付买单。"
## [2] "沃尔玛移动支付应用已经部  署在其全美4,600家超市中。"
# gsub(pattern, replacement, x, ...)
gsub(' ', '', messySentences)
## [1] "沃尔玛还与微信跨界合作,顾客可通过沃尔玛微信服务号的付款功能在实体门店秒付买单。"
## [2] "沃尔玛移动支付应用已经部署在其全美4,600家超市中。"

Extract substrings in a character vector

# extract substrings: substr(x, start, stop)
x <- c('月薪:5000元', '月薪:8000元')
substr(x,4,7)
## [1] "5000" "8000"

Your turn (1)

  1. Load text from the https://yanfei.site/docs/dpsa/BABAnews.txt and print it on screen. Text file contains some of the news of Alibaba.

  2. How many paragraphs are there in the article?

  3. Trim leading whitespaces of each paragraph (try ??trim).

  4. How many characters are there in the article?

  5. Collapse paragraphs into one and display it on the screen (un-list it).

  6. Does the text contain word ‘技术架构’?

  7. Split the article into sentences (by periods).

  8. Replace ‘双11’ with ‘双十一’.

Answer (1)

# 1
baba.news <- readLines("https://yanfei.site/docs/dpsa/BABAnews.txt",
                       encoding = 'UTF-8')
noquote(baba.news)

# 2
length(baba.news)

# 3
baba.news <- str_trim(baba.news)

# 4
nchar(baba.news)

# 5
baba.news.collapsed <- paste(baba.news, collapse = "")
cat(baba.news.collapsed)

# 6
grepl("技术架构", baba.news.collapsed)
grep('技术架构', baba.news)

# 7
strsplit(baba.news.collapsed, "。")

# 8
gsub("双11", "双十一", baba.news.collapsed)

Reference and further reading

Please see Text processing on Wiki for more details, examples, R packages and R functions used for text processing in R.



Web Scraping

We need data