Guest User

immoscrap.py

a guest
Apr 16th, 2012
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.62 KB | None | 0 0
  1. #!/usr/local/bin/python
  2.  
  3. # To compile this script, you will need Python 2.4, and the following packages:
  4. #
  5. # BeautifulSoup 3.0.3, to parse the HTML code
  6. #      http://www.crummy.com/software/BeautifulSoup/#Download
  7. #
  8. # PyWin32 for the optional Excel support
  9. #      http://www.python.net/crew/mhammond/win32
  10.  
  11. import sys
  12. import os.path
  13. import re
  14. import urllib2
  15. import threading
  16. import time
  17. import Queue
  18. from BeautifulSoup import BeautifulSoup, SoupStrainer
  19.  
  20. createCache = False
  21.  
  22. m = re.compile(r'\b(\d+)\b')
  23. def GetInt(p):
  24.     l = m.findall(p)
  25.     if len(l):
  26.         return l[0]
  27.     else:
  28.         return ""
  29.  
  30.  
  31. def GetInt2(p): return "".join(m.findall(p))
  32.  
  33.  
  34. class DownloadWorker(threading.Thread):
  35.     def __init__(self, codePostal):
  36.         threading.Thread.__init__(self)
  37.         self.__codePostal = codePostal
  38.  
  39.     def run(self):
  40.         liste = SeLogerScrapper(self.__codePostal).GetDepartement()
  41.         exportQueue.put([self.__codePostal, liste])
  42.  
  43.  
  44. class ExcelExporter:
  45.     def __init__(self):
  46.         try:   # Import COM if available
  47.             from win32com.client import Dispatch
  48.             self.__xlApp = Dispatch("Excel.Application")
  49.             self.__xlApp.Workbooks.Open(os.path.abspath("immoscrap.xls"))
  50.         except ImportError:
  51.             self.__xlApp = None
  52.    
  53.  
  54.     def Export(self, codePostal, liste):
  55.         if self.__xlApp is not None:
  56.             self.__xlApp.Run('SetupPage', codePostal)
  57.             for v in liste:
  58.                 self.__xlApp.Run('AddLine', v[0], v[1], v[2] )
  59.         else:
  60.             output = open ("prix_" + str(dep) + ".csv", "wb")
  61.             for t in liste:
  62.                 line = t[0] + ", " + t[1] + ", " + t[2] + '\n'
  63.                 output.write(line)
  64.             output.close
  65.  
  66.     def End(self):
  67.             self.__xlApp.Visible = 1
  68.             del self.__xlApp
  69.  
  70.  
  71. class SeLogerScrapper:
  72.     def __init__(self, codePostal):
  73.         self.__codePostal = codePostal
  74.         self.ads = SoupStrainer('table', attrs={'class' : re.compile('addchapeau|addpages')} )
  75.  
  76.     def GetNextPageNumber(self, soup):
  77.         try:
  78.             addPages = soup.find(attrs={'class' : 'addpages'} )
  79.             nextLink = addPages.find('td', align='right').a['href']
  80.             return GetInt2(nextLink)
  81.         except:
  82.             return 0
  83.    
  84.    
  85.     def DownloadPage(self, startPrice, pageNumber):
  86.         pageCacheName = "cache_" + str(self.__codePostal) +"_" + str(startPrice) +"_" + str(pageNumber) + ".html"
  87.         if not os.path.exists(pageCacheName):
  88.             print "* Download", self.__codePostal, " Prix :", startPrice, ", Page:" , pageNumber
  89.    
  90.             pageName = "http://www.seloger.com/recherche.htm?euro=1&idtt=2&rnd=121&cp="
  91.             url= pageName + str(self.__codePostal)
  92.  
  93.             if False: #appartement
  94.                 url += "&idtypebien=1"
  95.             else:
  96.                 url += "&idtypebien=2"
  97.    
  98.             if startPrice:
  99.                 url+="&pxmin=" + str(startPrice)
  100.                
  101.             if pageNumber:
  102.                 url+="&immobw_ann_qrypg=" + str(pageNumber)
  103.        
  104.             if 0: #if you have a proxy, set it here
  105.                 proxy_handler = urllib2.ProxyHandler({'http': 'http://xx.xx.xx.xx:80'} )
  106.                 opener = urllib2.build_opener(proxy_handler)
  107.                 urllib2.install_opener(opener)
  108.                
  109.             target = urllib2.urlopen(url).read()
  110.            
  111.             if createCache :
  112.                 output = open (pageCacheName, "wb")
  113.                 output.write(target)
  114.                 output.close
  115.    
  116.         else:
  117.             print "* Cache(", self.__codePostal, "). Prix :", startPrice, ", Page:" , pageNumber
  118.             target = open (pageCacheName, "rb")
  119.            
  120.         soup = BeautifulSoup(target, fromEncoding="utf-8", parseOnlyThese=self.ads)
  121.        
  122.         return soup
  123.    
  124.    
  125.     def ExtractAds(self, soup, liste):
  126.         annonceTags = soup.findAll(attrs={'class' : 'addchapeau'} )
  127.         for annonce in annonceTags:
  128.             id = annonce.tr.td.span.a['href']
  129.             price = annonce.find(attrs={'class':'addprixeu'}).contents[0]
  130.             surface = annonce.tr.td.contents[2]
  131.             liste.append ([id, GetInt(surface), GetInt2(price) ])
  132.         return liste
  133.    
  134.    
  135.     def GetDepartement(self):
  136.         liste = []
  137.         startPrice = 0
  138.         departmentDone = False
  139.         while not departmentDone:
  140.             pageNumber = nextPage = 1
  141.             pagesToDo=True
  142.    
  143.             while pagesToDo:
  144.                 soup = self.DownloadPage(startPrice, pageNumber )
  145.                 self.ExtractAds(soup, liste)
  146.    
  147.                 nextPage = self.GetNextPageNumber(soup)
  148.                 if (nextPage==0):
  149.                     pagesToDo=False
  150.                 else:
  151.                     pageNumber = nextPage
  152.            
  153.             if str(pageNumber)!="29":
  154.                 departmentDone = True
  155.             else:
  156.                 lastPrice = startPrice
  157.                 startPrice = liste[-1][2]
  158.                 if (startPrice==lastPrice):
  159.                     departmentDone = True
  160.    
  161.         return liste
  162.  
  163.  
  164. exportQueue = Queue.Queue(0)
  165.  
  166. print "Entrez la liste des codes postaux (separes par espace) : "
  167. deps = sys.stdin.readline().split()
  168.  
  169. xl = ExcelExporter()
  170.  
  171. for departement in deps:
  172.     DownloadWorker(departement).start()
  173.  
  174. for departement in deps:
  175.     item = exportQueue.get()
  176.     if len(item[1]):
  177.         xl.Export(*item)
  178.     else:
  179.         print "Le code postal", item[0], "n'a pas produit de resultats."
  180. xl.End()
Advertisement
Add Comment
Please, Sign In to add comment