图片懒加载技术

什么是图片懒加载技术

图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。

如何实现图片懒加载技术

在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original......)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。

如何破解图片懒加载技术

其实很简单,在对标签属性进行定位的时候,仔细观察它真正的属性进行提取。

例如:

import requests
from lxml import etree def main():
responses = requests.get(url=url, headers=headers)
coding = responses.apparent_encoding
responses.encoding = coding
res_text = responses.text
# 创建etree对象
tree = etree.HTML(res_text)
div_lst = tree.xpath('//div[@id="container"]/div')
for one_div in div_lst:
image_name = one_div.xpath('.//img/@alt')[0]
image_url = one_div.xpath('.//img/@src2')
print(image_name)
print(image_url) if __name__ == '__main__':
headers = {"User-Agent":'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0'}
url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'
main()

以上例子中就将src属性换为了src2属性。

selenium

1 什么是Selenium?

selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作。 
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。

2 前期准备

selenium安装就不再概述了

查看自己的谷歌浏览器版本

查看自己对用的谷歌驱动: https://blog.csdn.net/huilan_same/article/details/51896672

下载自己的谷歌驱动: http://chromedriver.storage.googleapis.com/index.html

这里我下载是:

然后加压后把它放到python解释器的scripts目录中即可.

3 简单示例
from selenium import webdriver
from time import sleep # 启动你的谷歌浏览
driver = webdriver.Chrome()
# 用get方法打开百度首页
driver.get('https://www.baidu.com')
# 找到第一个链接标签的文本并点击
driver.find_elements_by_link_text('设置')[0].click()
# 睡一秒
sleep(1)
# 找到搜索设置并点击
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2)
# 找到id为nr的标签
ch = driver.find_element_by_id('nr')
sleep(1)
# 选择第3个标签点击
# ch.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
ch.find_element_by_xpath('.//option[3]').click()
sleep(2)
# 保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2)
# 处理弹出的警告
driver.switch_to_alert().accept()
sleep(2)
# 网搜索框里传入数据
driver.find_element_by_id('kw').send_keys('nba')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
sleep(2)
# 关闭驱动
driver.close()
# 关闭浏览器
driver.quit()

这是一个设置百度搜索每个页面显示50条数据并搜索nba的程序

Selenium支持的浏览器非常多,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS,也就是后面要说的内容。

4 webdriver的元素定位
# 通过id属性
find_element_by_id()
# 通过name属性
find_element_by_name()
# 通过class的名字
find_element_by_class_name()
# 通过标签的名字
find_element_by_tag_name()
# 通过链接标签的文本
find_element_by_link_text()
# 通过链接标签的部分文本
find_element_by_partial_link_text()
# 通过xpath
find_element_by_xpath()
# 通过css选择器
find_element_by_css_selector()
注意:
1 find_element_by_xxx找的是第一个符合条件的标签,find_elements_by_xxx找的是所有符合条件的标签。
2 elenium还提供了通用方法find_element(),它需要传入两个参数:查找方式By和值。实际上,它就是find_element_by_id()
这种方法的通用函数版本,比如find_element_by_id(id)就等价于find_element(By.ID, id),二者得到的结果完全一致。
5 对节点进行交互
# 通过id知道输入框
input = browser.find_element_by_id('q')
# 向里面出入文本MAC
input.send_keys('MAC')
# 清楚文本框
input.clear()
# 再传入一个文本IPhone
input.send_keys('IPhone')
# 通过classname找到一个事件
button = browser.find_element_by_class_name('btn-search')
# 点击它
button.click()
6 动作链

什么是动作链呢?

在节点交互中,交互动作都是针对某个节点执行的。比如对于输入框,就调用它输入和清空的方法,对于按钮,就调用它点击的方法,其实还有一些操作,它们没有特定的执行对象,比如鼠标拖拽,键盘按键,它们使用另一种方式来执行,就是动作链。

以下例子演示了把一个节点从一处拖动到另一处:

from selenium import webdriver
from time import sleep
from selenium.webdriver import ActionChains driver = webdriver.Chrome()
# 菜鸟教程的js演示代码
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
driver.get(url)
# 进入嵌套的页面
driver.switch_to.frame('iframeResult')
# 点位要拖动的标签
start = driver.find_element_by_css_selector('.ui-draggable')
# 拖动的目标标签
end = driver.find_element_by_css_selector('.ui-droppable')
# 创建一个鼠标事件
actions = ActionChains(driver)
# 点击要拖动的标签不松动
sleep(1)
actions.click_and_hold(start).perform()
# 然后移动到另一个标签
actions.move_to_element(end).perform()
# 往x轴移动40,y轴移动20
sleep(1)
actions.move_by_offset(xoffset=40, yoffset=20).perform()
# 释放动作
actions.release()

可能有人会对driver.switch_to.frame('iframeResult')这句代码有疑问

这个就是frame嵌套的。

在 web 应用中经常会出现 iframe 嵌套的应用,假设页面上有 A、B 两个 iframe,其中 B 在 A 内,那么定位 B 中的内容则需要先到 A,然后再到 B。

所以我们使用driver.switch_to.frame('iframeResult')直接进入嵌套的页面。

7 执行js

有些api是selenium没有提供的,比如下拉进度条,但是可以通过吗模拟运行js来实现。

from selenium import webdriver
from time import sleep driver = webdriver.Chrome()
driver.get('https://www.jd.com/')
# 移动到页面最底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
sleep(2)
# 执行alert123这个代码 就是弹出123
driver.execute_script("alert('123')")

这一块自动化测试用的挺多的,想学自动化测试的同学可以多学习下。

8 获取节点信息

通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。

selenium自己也提供了提取节点信息的方法,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了,非常方便。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as E
from selenium.webdriver.support.wait import WebDriverWait driver = webdriver.Chrome()
# 访问亚马逊首页
driver.get("https://www.amazon.cn/")
# 显示等待10秒
wait = WebDriverWait(driver, 10)
# 判断元素是否被加载到了dom中
wait.until(E.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer')))
# 通过选择器找到这个元素
tag=driver.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img')
#获取标签属性,
print(tag.get_attribute('src'))
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)
driver.close()
9 延时等待

在selenium中,get()方法会在页面框加载结束后,结束执行。此时如果获得get_source,可能不是浏览器完全加载完成后的页面,某些额外的js,ajax可能不一定获取到,所以需要延时等待一下,确保节点加载出来了,这里等待的方式有2中:显式等待和隐式等待。

1 显式等待

上个例子就用到了显式等待,显式等待会设置一个固定的等待时间,但是实际情况是由于外界因素的影响,我们也不可能判断出需要多少时间,所有显示等待还有一种写法,如果在规定时间加载出了这个节点,就对这个节点进行操作,如果没有加载出,就抛出超时异常。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as E
from selenium.webdriver.support.wait import WebDriverWait driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
input_tag = driver.find_element_by_id('kw')
input_tag.send_keys('美女')
# 模拟键盘回车键
input_tag.send_keys(Keys.ENTER)
# 创建一个显式等待
wait = WebDriverWait(driver, 10)
# 等待直到加载出content_left(content是左半区)
wait.until(E.presence_of_element_located((By.ID, 'content_left')))
content = driver.find_element(By.CSS_SELECTOR, "#content_left")
print(content)
driver.close()

如果将webDriverWait中的时间设置过低,会报错:

2 隐式等待

当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome()
# 设置隐式等待
driver.implicitly_wait(10)
driver.get('https://www.baidu.com/')
input_tag = driver.find_element_by_id('kw')
input_tag.send_keys('NBA')
# 模拟键盘回车键
input_tag.send_keys(Keys.ENTER)
content = driver.find_element(By.CSS_SELECTOR, "#content_left")
print(content)
driver.close()
10 cookie

使用selenium还可以对cookie进行操作,获取,添加,删除cookie:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.zhihu.com/explore')
# 获取cookie
print(driver.get_cookies())
# 添加cookie
driver.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(driver.get_cookies())
# 删除cookie
driver.delete_all_cookies()
print(driver.get_cookies())
[{'domain': '.zhihu.com', 'httpOnly': False, 'name': 'l_n_c', 'path': '/', 'secure': False, 'value': ''}, {'domain': 'www.zhihu.com', 'expiry': 1555763561.220174, 'httpOnly': False, 'name': 'tgw_l7_route', 'path': '/', 'secure': False, 'value': '537a925d07d06cecbf34cd06a153f671'}, {'domain': '.zhihu.com', 'expiry': 1650370661.220268, 'httpOnly': False, 'name': 'q_c1', 'path': '/', 'secure': False, 'value': '9ca2467feeaa4987a63360951034c876|1555762662000|1555762662000'}, {'domain': 'www.zhihu.com', 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': '270095e8c0bc05224a3eb61674d59ce0'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220341, 'httpOnly': False, 'name': 'r_cap_id', 'path': '/', 'secure': False, 'value': '"ZjhkMmMxZWE5NjlhNDY3OWE4ODA1NjI4MjhkYzc0Y2Y=|1555762662|257a989723432c66a22d10794cd998b22d419794"'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220391, 'httpOnly': False, 'name': 'cap_id', 'path': '/', 'secure': False, 'value': '"NTY2OWZiYmI2ODdlNDFkZWE1MzBiZTEyYTQ5MDFmYzk=|1555762662|5c5e5d6a7150c0da99f86af9d85cc63cafbea752"'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220438, 'httpOnly': False, 'name': 'l_cap_id', 'path': '/', 'secure': False, 'value': '"Njk2NWI1ZTIxYjg2NGZhZDhiOGJiYjM5ODg0Y2U2ZmM=|1555762662|6a4e7d4ab33c72012e5bf133ffadfe34aa88b8eb"'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': 'n_c', 'path': '/', 'secure': False, 'value': ''}, {'domain': '.zhihu.com', 'expiry': 1650370664.061236, 'httpOnly': False, 'name': 'd_c0', 'path': '/', 'secure': False, 'value': '"AJDm50C_Tg-PTkHkupcfIBQqf8xnPhGsu4M=|1555762665"'}, {'domain': '.zhihu.com', 'expiry': 1633522664.358119, 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': 'mzatpYVVTALiHdu45yqz9q4yljxCPZ7n'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '_zap', 'path': '/', 'secure': False, 'value': 'ec95407d-3b81-4e43-81d5-277adf4b33b9'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '__utma', 'path': '/', 'secure': False, 'value': '51854390.2113439272.1555762665.1555762665.1555762665.1'}, {'domain': '.zhihu.com', 'expiry': 1555764464, 'httpOnly': False, 'name': '__utmb', 'path': '/', 'secure': False, 'value': '51854390.0.10.1555762665'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': '__utmc', 'path': '/', 'secure': False, 'value': ''}, {'domain': '.zhihu.com', 'expiry': 1571530664, 'httpOnly': False, 'name': '__utmz', 'path': '/', 'secure': False, 'value': '51854390.1555762665.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '__utmv', 'path': '/', 'secure': False, 'value': '51854390.000--|3=entry_date=20190420=1'}]
[{'domain': '.zhihu.com', 'httpOnly': False, 'name': 'l_n_c', 'path': '/', 'secure': False, 'value': ''}, {'domain': 'www.zhihu.com', 'expiry': 1555763561.220174, 'httpOnly': False, 'name': 'tgw_l7_route', 'path': '/', 'secure': False, 'value': '537a925d07d06cecbf34cd06a153f671'}, {'domain': '.zhihu.com', 'expiry': 1650370661.220268, 'httpOnly': False, 'name': 'q_c1', 'path': '/', 'secure': False, 'value': '9ca2467feeaa4987a63360951034c876|1555762662000|1555762662000'}, {'domain': 'www.zhihu.com', 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': '270095e8c0bc05224a3eb61674d59ce0'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220341, 'httpOnly': False, 'name': 'r_cap_id', 'path': '/', 'secure': False, 'value': '"ZjhkMmMxZWE5NjlhNDY3OWE4ODA1NjI4MjhkYzc0Y2Y=|1555762662|257a989723432c66a22d10794cd998b22d419794"'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220391, 'httpOnly': False, 'name': 'cap_id', 'path': '/', 'secure': False, 'value': '"NTY2OWZiYmI2ODdlNDFkZWE1MzBiZTEyYTQ5MDFmYzk=|1555762662|5c5e5d6a7150c0da99f86af9d85cc63cafbea752"'}, {'domain': '.zhihu.com', 'expiry': 1558354661.220438, 'httpOnly': False, 'name': 'l_cap_id', 'path': '/', 'secure': False, 'value': '"Njk2NWI1ZTIxYjg2NGZhZDhiOGJiYjM5ODg0Y2U2ZmM=|1555762662|6a4e7d4ab33c72012e5bf133ffadfe34aa88b8eb"'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': 'n_c', 'path': '/', 'secure': False, 'value': ''}, {'domain': '.zhihu.com', 'expiry': 1650370664.061236, 'httpOnly': False, 'name': 'd_c0', 'path': '/', 'secure': False, 'value': '"AJDm50C_Tg-PTkHkupcfIBQqf8xnPhGsu4M=|1555762665"'}, {'domain': '.zhihu.com', 'expiry': 1633522664.358119, 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': 'mzatpYVVTALiHdu45yqz9q4yljxCPZ7n'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '_zap', 'path': '/', 'secure': False, 'value': 'ec95407d-3b81-4e43-81d5-277adf4b33b9'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '__utma', 'path': '/', 'secure': False, 'value': '51854390.2113439272.1555762665.1555762665.1555762665.1'}, {'domain': '.zhihu.com', 'expiry': 1555764464, 'httpOnly': False, 'name': '__utmb', 'path': '/', 'secure': False, 'value': '51854390.0.10.1555762665'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': '__utmc', 'path': '/', 'secure': False, 'value': ''}, {'domain': '.zhihu.com', 'expiry': 1571530664, 'httpOnly': False, 'name': '__utmz', 'path': '/', 'secure': False, 'value': '51854390.1555762665.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)'}, {'domain': '.zhihu.com', 'expiry': 1618834664, 'httpOnly': False, 'name': '__utmv', 'path': '/', 'secure': False, 'value': '51854390.000--|3=entry_date=20190420=1'}, {'domain': 'www.zhihu.com', 'expiry': 2186482664, 'httpOnly': False, 'name': 'name', 'path': '/', 'secure': True, 'value': 'germey'}]
[]
11 异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchFrameException try:
driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
driver.switch_to.frame('iframssseResult')
except TimeoutException as e:
print(e)
except NoSuchFrameException as e:
print(e)
finally:
driver.close()

超时等待哪里就可以这样写。

phantomJs

phantomJs是一款无界面的浏览器,其自动化操作流程和上面的谷歌浏览器是一致的。

由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现。

from selenium import webdriver
import time # exe路径
path = r'C:\phantomjs-2.1.1-windows\bin\phantomjs.exe'
driver = webdriver.PhantomJS(path)
driver.get("https://www.baidu.com")
time.sleep(2)
driver.save_screenshot(r'baidu.png')
my_input = driver.find_element_by_id('kw')
my_input.send_keys('nba')
driver.save_screenshot(r'nba.png')
# 查找搜索按钮
button = driver.find_elements_by_class_name('s_btn')[0].click()
time.sleep(3)
driver.save_screenshot(r'show.png')
driver.close()
driver.quit()

使用selenum+phantomJs可以解决某些网页js动态加载问题。

selenium+phantomJs爬取豆瓣电影的电影信息

首先来看下这个页面:https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action=

查看他的网页源代码:发现它是js动态加载显示的

from selenium import webdriver
import time def main():
path = r'C:\phantomjs-2.1.1-windows\bin\phantomjs.exe'
driver = webdriver.PhantomJS(path)
driver.get(url)
time.sleep(2)
driver.save_screenshot(r'1.png')
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.save_screenshot('2.png')
time.sleep(1)
html_source = driver.page_source
with open('source.html', 'w', encoding='utf-8') as f:
f.write(html_source)
driver.quit() if __name__ == "__main__":
url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='
main()

这样就可以拿到它的源码了:

谷歌无头浏览器 Headless Chrome

由于phantomJs已经停止了更新和维护,所以推荐使用谷歌的无头浏览器,这是一款无界面的谷歌浏览器

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep # 创建一个无头浏览器对象
chrome_options = Options()
# 设置它为无框模式
chrome_options.add_argument('--headless')
# 如果在windows上运行需要加代码
chrome_options.add_argument('--disable-gpu') browser = webdriver.Chrome(chrome_options=chrome_options)
browser.get('https://www.baidu.com/')
sleep(2)
browser.save_screenshot('first_page.png')
browser.quit()
使用谷歌无头浏览器爬取网易新闻的国内模块

单独写了一篇博客:https://www.cnblogs.com/xiaozx/p/10744604.html

python爬虫之selenium、phantomJs的更多相关文章

  1. Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容

    1,引言 在Python网络爬虫内容提取器一文我们详细讲解了核心部件:可插拔的内容提取器类gsExtractor.本文记录了确定gsExtractor的技术路线过程中所做的编程实验.这是第二部分,第一 ...

  2. [Python爬虫] :Selenium +phantomjs 利用 pyquery抓取脚本链接对应的内容

    抓取上面对应链接的网页的文章的内容 ele = element.attr("onclick") self.driver.execute_script(ele) sub_seleni ...

  3. [Python爬虫]使用Selenium操作浏览器订购火车票

    这个专题主要说的是Python在爬虫方面的应用,包括爬取和处理部分 [Python爬虫]使用Python爬取动态网页-腾讯动漫(Selenium) [Python爬虫]使用Python爬取静态网页-斗 ...

  4. Python爬虫教程-26-Selenium + PhantomJS

    Python爬虫教程-26-Selenium + PhantomJS 动态前端页面 : JavaScript: JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持 ...

  5. Python爬虫之selenium库使用详解

    Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...

  6. Python 爬虫利器 Selenium 介绍

    Python 爬虫利器 Selenium 介绍 转 https://mp.weixin.qq.com/s/YJGjZkUejEos_yJ1ukp5kw 前面几节,我们学习了用 requests 构造页 ...

  7. Python爬虫之selenium的使用(八)

    Python爬虫之selenium的使用 一.简介 二.安装 三.使用 一.简介 Selenium 是自动化测试工具.它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏 ...

  8. Python爬虫之selenium高级功能

    Python爬虫之selenium高级功能 原文地址 表单操作 元素拖拽 页面切换 弹窗处理 表单操作 表单里面会有文本框.密码框.下拉框.登陆框等. 这些涉及与页面的交互,比如输入.删除.点击等. ...

  9. python爬虫利器Selenium使用详解

    简介: 用pyhon爬取动态页面时普通的urllib2无法实现,例如下面的京东首页,随着滚动条的下拉会加载新的内容,而urllib2就无法抓取这些内容,此时就需要今天的主角selenium. Sele ...

随机推荐

  1. MySQL中group_concat函数深入理解

    本文通过实例介绍了MySQL中的group_concat函数的使用方法,比如select group_concat(name) . 一.MySQL中group_concat函数 完整的语法如下: gr ...

  2. 玩转Spring MVC (一)---控制反转(依赖注入)

    Spring的核心是控制反转,什么是控制反转呢?小编浅述一下自己的拙见,有不当之处还希望大家指出. 控制反转(IOC),也可以叫做依赖注入(DI),这两个词其实是一个概念. 控制反转,那是什么控制被反 ...

  3. Centos7下安装PHP5.5,5.6,7.0----(转载记录一下)

    由于centOS7 默认的php版本是5.4的,偏低,所以收录了一下怎样安装5.5/5.6/7.0版本 默认的版本太低了,手动安装有一些麻烦,想采用Yum安装的可以使用下面的方案: 1.检查当前安装的 ...

  4. Java Script 读书笔记 (三) 函数

    1. 函数作用域 在函数内部定义的变量,外部无法读取,称为"局部变量"(local variable). 变量v在函数内部定义,所以是一个局部变量,函数之外就无法读取. 函数内部定 ...

  5. 【ShoppingWebCrawler】-基于Webkit内核的爬虫蜘蛛引擎概述

    写在开头 在各个电商平台发展日渐成熟的今天.很多时候,我们需要一些平台上的基础数据.比如:商品分类,分类下的商品详细,甚至业务订单数据.电商平台大多数提供了相应的业务接口.允许ISV接入,用来扩展自身 ...

  6. Golang错误和异常处理的正确姿势

    Golang错误和异常处理的正确姿势 错误和异常是两个不同的概念,非常容易混淆.很多程序员习惯将一切非正常情况都看做错误,而不区分错误和异常,即使程序中可能有异常抛出,也将异常及时捕获并转换成错误.从 ...

  7. Instrumentation(3)

    摘要: Instrumentation  类加载过程  Instrumentation与Transformer  Instrumentation与Transformer的关系  Instrumenta ...

  8. ThreadPoolExecutor简介

    ThreadPoolExecutor简介 并发包中提供的一个线程池服务 23456789 public ThreadPoolExecutor(int corePoolSize,//线程池维护线程的最少 ...

  9. BZOJ_1500_[NOI2005]维修数列_splay

    BZOJ_1500_[NOI2005]维修数列_splay 题意: 分析: 节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和 插入:重新建一棵树,把pos旋到根,把po ...

  10. Twitter分布式自增ID算法snowflake原理解析

    以JAVA为例 Twitter分布式自增ID算法snowflake,生成的是Long类型的id,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特(0和1). 那么一个 ...