2016-12-29 178 views
0

我写了一个简单的解析器,它访问网站的主页和主页上的内部链接。基本上它从主页开始进入网站结构1级,并搜索匹配正则表达式的字符串。它也执行JS。适用于电子邮件,电话号码或任何格式良好的数据。这是代码:网站抓取器每隔几秒就抓取一次网站

pages = set() 
def getPage(startUrl): 
    user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11' 
    dcap = dict(DesiredCapabilities.PHANTOMJS) 
    dcap["phantomjs.page.settings.userAgent"] = (user_agent) 

    driver = webdriver.PhantomJS(executable_path="/Users/mainuser/Downloads/phantomjs-2.1.1-macosx/bin/phantomjs", desired_capabilities=dcap) 
#  print("in get page: "+startUrl) 
    try: 
     driver.set_page_load_timeout(10) 
     driver.get(startUrl) 
     return BeautifulSoup(driver.page_source,"html.parser") 
    except: 
     print("returning NOne") 
     return None 

def traverseHomePage(startUrl): 

    if startUrl.endswith("/"): 
     startUrl = startUrl[:-1] 
    try: 
     driver = webdriver.PhantomJS(executable_path="/Users/mainuser/Downloads/phantomjs-2.1.1-macosx/bin/phantomjs") 
     driver.get(startUrl) 
    except HTTPError as e: 
     print(e) 
#   print(pageUrl+" ") 
     pass 
    except URLError as e: 
     print(e) 
     pass 
    else: 

     bsObj = BeautifulSoup(driver.page_source,"html.parser") 

     text = str(bsObj) 
     listRegex = re.findall(r'someregexhere', text) 
     print(listRegex+" do something with data") 


     for link in bsObj.findAll("a", href=re.compile("^((?!#|javascript|\.png|\.jpg|\.gif).)*$")): 
      if 'href' in link.attrs: 

       if ("http://" in link.attrs['href'] or "https://" in link.attrs['href']) and startUrl in link.attrs['href']: 
        print("internal aboslute: "+startUrl+" is in "+link.attrs['href']) 
        #absolute link 
        if 'href' in link.attrs: 
         if link.attrs['href'] not in pages: 
          #We have encountered a new page 
          newPage = link.attrs['href'] 
          oneLevelDeep(newPage) 

       elif ("http://" in link.attrs['href'] or "https://" in link.attrs['href'] or "mailto" in link.attrs['href']) and (startUrl not in link.attrs['href']): 
        print("outside link"+link.attrs['href']) 
#      print(link.attrs['href']) 
        continue 
       else: 
        print("internal relative: "+link.attrs['href']) 
        #relative link 
        if 'href' in link.attrs: 
         if link.attrs['href'] not in pages: 
            #We have encountered a new page 
            newPage = link.attrs['href'] 
            pages.add(newPage) 

            if newPage.startswith("/"): 
             pass 
      #        print("/"+newPage) 
            else: 
             newPage = "/"+newPage 
            pages.add(newPage) 
            oneLevelDeep(startUrl+newPage) 

def oneLevelDeep(startUrl): 
#  print(startUrl) 
    if startUrl.endswith("/"): 
     startUrl = startUrl[:-1] 

    try: 
#   print("stUrl: "+startUrl+pageUrl) 
     bsObj = getPage(startUrl) 
     if bsObj != "None": 
      text = str(bsObj) 

      text = str(bsObj) 
     listRegex = re.findall(r'someregexhere', text) 
     print(listRegex+" do something with data") 
#   
    except HTTPError as e: 
#   print(e) 
#   print(pageUrl+" ") 
     pass 
    except URLError as e: 
#   print(e) 
     pass 

使用示例:traverseHomePage("http://homepage.com")

我跑这刮了一段时间,这是令人难以置信的慢。我在Eclipse中复制了我的项目8次,并且仍然只在12小时内搜索了1000页,我可以做些什么来提高速度?我严重怀疑谷歌机器人每天仅索引250页。

我认为瓶颈是每分钟机器人制作页面的数量。它每两秒钟完成一次。我读过关于每秒钟发出50个请求的机器人(并且你不应该那样做)。这不是这种情况。

我该怎么做才能提高抓取速度?我从Eclipse本地主机运行代码。如果我转移到服务器会有帮助吗?我应该以某种方式告诉服务器不要发送图像,以便使用更少的带宽?是否有可能发出异步请求?多个脚本是否同时运行?任何想法都欢迎。

回答

1

问题是,您正在加载网页,就像浏览器访问该页面一样。如果你打开homepage.com并转到开发者菜单,然后进入网络(至少在Chrome上),你会注意到这个页面需要很长时间才能加载。在我的情况下,它需要7秒,最后一个文件是谷歌地图认证文件。

Google可以快速解析事情,因为它在服务器上具有服务器来执行解析,并且由于它只查看几个文件,从根目录开始访问该页面上的每个链接以及每个后续页面上的每个链接那。它不需要等待整个页面加载。它只需要每个网站的原始html。

等待JavaScript,并下载整个网站,CSS和所有(而不是一个HTML文件)是什么是放缓你的搜索。我会使用请求来获取裸露的HTML并从那里开始工作。

+0

谢谢你停下来。由于我经常搜索动态数据,所以没有选择从解析中排除JS。你能提供一些关于如何下载html和js的代码吗? – sanjihan

+0

当你说动态的时候,你的意思是在运行时生成,还是可能在JavaScript文件中预先确定? – arlyon

+0

请求模块使得下载网页的html变得非常容易,此时您可以搜索它以查找js文件和其他链接,并随时将它们添加到队列中。 – arlyon