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.

125 lines
4.1 KiB

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