automated Pipeline for parsing profiles of politically exposed persons (PEP) into Wikidata
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
6.9 KiB

  1. import os
  2. import yaml
  3. import json
  4. import urllib.request, urllib.error, urllib.parse
  5. from lxml import etree
  6. import lxml.html
  7. import lxml.html.soupparser
  8. class membersParliamentCrawler(object):
  9. def __init__(self, configFile):
  10. with open(configFile, "r") as stream:
  11. try:
  12. self.config = yaml.safe_load(stream)
  13. except yaml.YAMLError as exc:
  14. print(exc)
  15. # input list of countries in form of ['nicaragua', 'honduras', .. , 'mexico']
  16. def downloadMemberListPagesOfCountries(self, listOfCountries):
  17. # download only html pages of the countries specified in input
  18. for country in listOfCountries:
  19. for key in self.config:
  20. if key in listOfCountries:
  21. try:
  22. memberList = self.config.get(key).get('memberList')
  23. except Exception as e:
  24. print("There is a problem with the entry memberList in the config.yaml - the original error message is:", e)
  25. try:
  26. memberListLink = memberList.get('link')
  27. except Exception as e:
  28. print("No memberListLink defined in config.yaml - the original error message is:", e)
  29. # download the html page of the List of Members
  30. response = urllib.request.urlopen(memberListLink)
  31. webContent = response.read().decode('UTF-8')
  32. # save interim results to files
  33. f = open('pages/' + key +'MemberList.html', 'w+')
  34. f.write(webContent)
  35. f.close
  36. def parseMemberListData2dictionary(self, listOfCountries):
  37. for country in listOfCountries:
  38. try:
  39. #use soupparser to handle broken html
  40. tree = lxml.html.soupparser.parse('pages/' + country + 'MemberList.html')
  41. # for e in tree.iter():
  42. #
  43. # print(e.tag)
  44. #
  45. # for e in tree.xpath('//html//body//form//table//tr//td//table//tr'):
  46. #
  47. # #print(etree.tostring(e).decode())
  48. dictionaryMemberList = {}
  49. countryConf = self.config.get(country)
  50. countryDomain = countryConf.get('domain')
  51. countryConfMemberList = countryConf.get('memberList')
  52. countryConfMemberListParent = countryConfMemberList.get('parent')
  53. countryConfMemberListChildName = countryConfMemberList.get('child-name')
  54. countryConfMemberListChildLink = countryConfMemberList.get('child-link')
  55. for n in range(len(tree.xpath(countryConfMemberListParent))):
  56. name = tree.xpath(countryConfMemberListParent + '[' + str(n) + ']' + countryConfMemberListChildName)
  57. link = tree.xpath(countryConfMemberListParent + '[' + str(n) + ']' + countryConfMemberListChildLink)
  58. if len(name) > 0:
  59. dictionaryMemberList[n] = {}
  60. dictionaryMemberList[n]['name'] = name[0]
  61. if countryDomain in link[0]:
  62. dictionaryMemberList[n]['link'] = link[0]
  63. if countryDomain not in link[0]:
  64. dictionaryMemberList[n]['link'] = countryDomain + link[0]
  65. except Exception as e:
  66. print('parsing the html did not work. Possibly you first have to downloadMemberListPagesOfCountries(). The original error message is:', e)
  67. # save interim results to files
  68. f = open('output/' + country +'MemberList.txt', 'w+')
  69. f.write(str(dictionaryMemberList))
  70. f.close
  71. def downloadMemberDataHtmls(self, listOfCountries):
  72. for country in listOfCountries:
  73. f = open('output/' + country +'MemberList.txt')
  74. text = f.read()
  75. dictionaryMemberList = eval(text)
  76. for memberid in dictionaryMemberList:
  77. memberLink = dictionaryMemberList[memberid]['link']
  78. # download the html page of the Member
  79. response = urllib.request.urlopen(memberLink)
  80. webContent = response.read().decode('UTF-8')
  81. # save interim results to files
  82. filename = 'pages/' + country + '/' + str(memberid) +'.html'
  83. os.makedirs(os.path.dirname(filename), exist_ok=True)
  84. f = open( filename, 'w+')
  85. f.write(webContent)
  86. f.close
  87. def parseMemberData2dictionary(self, listOfCountries):
  88. for country in listOfCountries:
  89. print('started to parse data of member of ' + country + ' ..')
  90. f = open('output/' + country +'MemberList.txt')
  91. text = f.read()
  92. dictionaryMemberList = eval(text)
  93. countryConf = self.config.get(country)
  94. countryDomain = countryConf.get('domain')
  95. countryConfMember = countryConf.get('member')
  96. countryConfMemberInfo1 = countryConfMember.get('info-1')
  97. countryConfMemberInfo1Parent = countryConfMemberInfo1.get('parent')
  98. countryConfMemberInfo1ChildPoliticalParty = countryConfMemberInfo1.get('child-politicalParty')
  99. for memberid in dictionaryMemberList:
  100. print('started to parse data of member with name ' + dictionaryMemberList[memberid]['name'] + ' ..')
  101. filename = 'pages/' + country + '/' + str(memberid) +'.html'
  102. tree = lxml.html.soupparser.parse(filename)
  103. politicalParty = tree.xpath(countryConfMemberInfo1Parent + countryConfMemberInfo1ChildPoliticalParty)
  104. print('oi', politicalParty)
  105. if len(politicalParty) > 0:
  106. dictionaryMemberList[memberid]['political party'] = politicalParty[0]
  107. f = open('output/' + country +'MemberList.txt', 'w+')
  108. f.write(str(dictionaryMemberList))
  109. f.close