Sitemap generator
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.

128 lines
4.2 KiB

9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
8 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
  1. import urlparse
  2. import mechanize
  3. import re
  4. try:
  5. import sys
  6. if 'threading' in sys.modules:
  7. del sys.modules['threading']
  8. print('threading module loaded before patching!')
  9. print('threading module deleted from sys.modules!\n')
  10. from gevent import monkey, pool
  11. monkey.patch_all()
  12. gevent_installed = True
  13. except:
  14. print("Gevent does not installed. Parsing process will be slower.")
  15. gevent_installed = False
  16. class Crawler:
  17. def __init__(self, url, outputfile='sitemap.xml', logfile='error.log', oformat='xml'):
  18. self.url = url
  19. self.logfile = open(logfile, 'a')
  20. self.oformat = oformat
  21. self.outputfile = outputfile
  22. # create lists for the urls in que and visited urls
  23. self.urls = set([url])
  24. self.visited = set([url])
  25. self.exts = ['htm', 'php']
  26. self.allowed_regex = '\.((?!htm)(?!php)\w+)$'
  27. def set_exts(self, exts):
  28. self.exts = exts
  29. def allow_regex(self, regex=None):
  30. if regex is not None:
  31. self.allowed_regex = regex
  32. else:
  33. allowed_regex = ''
  34. for ext in self.exts:
  35. allowed_regex += '(!{})'.format(ext)
  36. self.allowed_regex = '\.({}\w+)$'.format(allowed_regex)
  37. def crawl(self, echo=False, pool_size=1):
  38. self.echo = echo
  39. self.regex = re.compile(self.allowed_regex)
  40. if gevent_installed and pool_size > 1:
  41. self.pool = pool.Pool(pool_size)
  42. self.pool.spawn(self.parse_gevent)
  43. self.pool.join()
  44. else:
  45. while len(self.urls) > 0:
  46. self.parse()
  47. if self.oformat == 'xml':
  48. self.write_xml()
  49. elif self.oformat == 'txt':
  50. self.write_txt()
  51. def parse_gevent(self):
  52. self.parse()
  53. while len(self.urls) > 0 and not self.pool.full():
  54. self.pool.spawn(self.parse_gevent)
  55. def parse(self):
  56. if self.echo:
  57. if not gevent_installed:
  58. print('{} pages parsed :: {} pages in the queue'.format(len(self.visited), len(self.urls)))
  59. else:
  60. print('{} pages parsed :: {} parsing processes :: {} pages in the queue'.format(len(self.visited), len(self.pool), len(self.urls)))
  61. # Set the startingpoint for the spider and initialize
  62. # the a mechanize browser object
  63. if not self.urls:
  64. return
  65. else:
  66. url = self.urls.pop()
  67. br = mechanize.Browser()
  68. try:
  69. response = br.open(url)
  70. if response.code >= 400:
  71. self.errlog("Error {} at url {}".format(response.code, url))
  72. return
  73. for link in br.links():
  74. newurl = urlparse.urljoin(link.base_url, link.url)
  75. # print(newurl)
  76. if self.is_valid(newurl):
  77. self.visited.update([newurl])
  78. self.urls.update([newurl])
  79. except Exception, e:
  80. self.errlog(e.message)
  81. br.close()
  82. del(br)
  83. def is_valid(self, url):
  84. if '#' in url:
  85. url = url[:url.find('#')]
  86. if url in self.visited:
  87. return False
  88. if self.url not in url:
  89. return False
  90. if re.search(self.regex, url):
  91. return False
  92. return True
  93. def errlog(self, msg):
  94. self.logfile.write(msg)
  95. self.logfile.write('\n')
  96. def write_xml(self):
  97. of = open(self.outputfile, 'w')
  98. of.write('<?xml version="1.0" encoding="utf-8"?>\n')
  99. of.write('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">\n')
  100. url_str = '<url><loc>{}</loc></url>\n'
  101. while self.visited:
  102. of.write(url_str.format(self.visited.pop()))
  103. of.write('</urlset>')
  104. of.close()
  105. def write_txt(self):
  106. of = open(self.outputfile, 'w')
  107. url_str = '{}\n'
  108. while self.visited:
  109. of.write(url_str.format(self.visited.pop()))
  110. of.close()