一个同学的项目需要一些网站的首页的截图,网站数量大概有几千个,这么多的网站当然要用爬虫去爬了
百度出来一个看起来靠谱的方法,用了selenium库,例程如下:
| from selenium import webdriver url = "http://baidu.com" picName = "baidu.png" brower=webdriver.Chrome() brower.get(url) brower.save_screenshot(picName) brower.close()
|
试了一下很成功,然而真正用起来却踩了无数的坑
- 网页下载图片是需要时间的,而
brower.get(url)
这个函数不等到所有的资源都加载完是不会退出的
- 几千个网址里面有一些是已经废弃的假网站,
brower.get(url)
无法识别出来,只会一直等它们返回内容
brower=webdriver.Chrome()
会打开一个浏览器窗口,据我观察发现,如果这个浏览器打开网页后出现了网址跳转,拒绝连接等情况,python程序就不能控制这个浏览器窗口了,导致brower.close()
不能正常执行,浏览器关不掉
于是我对于各个问题都研究出了解决方案
- 针对第一个坑,使用
browser.set_page_load_timeout(10)
给网页加载设定一个时限,如果超时的话就会抛出TimeoutException
异常,然后我们再执行browser.execute_script('window.stop()')
用javascript使网页停止加载。
- 第二个坑,是对方网站坑我们,所以我们就不截图了。但是如果程序一直阻塞也不是办法,所以还是给程序设定一个时限,如果超时就强制停止。这里我用的是
@timeout_decorator.timeout(12)
这个装饰器
brower.close()
关不掉浏览器,那就直接调用shell命令kill
掉不就行了
无数次debug后,我终于写出了能用的代码。
回过头来一想,“浏览器崩了就崩了,直接kill掉”这个操作不就是“let it crash”思想的体现吗。有了异常情况如果不能正确处理,就应该任其崩溃,而不是以错误状态继续执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import TimeoutException import csv import threading import timeout_decorator import os csvName = "out.csv"
@timeout_decorator.timeout(12) def shot(browser, url,picName): print( url , picName) try: browser.get(url) except TimeoutException as err: print(err) browser.execute_script('window.stop()') finally: browser.save_screenshot(picName)
def main(): with open(csvName) as f: reader = csv.reader(f) cnt = 1 for i in list(reader): url = i[3] if cnt%10 == 0: os.system("ps -aux | grep chrome | grep -v grep | awk '{print $2}' | xargs kill") picName = str(cnt) + ".png" cnt=cnt+1 browser = webdriver.Chrome() browser.set_page_load_timeout(10) browser.set_window_size(1300,704) try: shot(browser,url,picName) except Exception as err: print(err) finally: browser.quit()
if __name__ == '__main__': main()
|