爬虫学习
urllib库
requests库
发送请求
传递 URL 参数
响应内容
二进制响应内容
JSON 响应内容
原始响应内容
定制请求头
更加复杂的 POST 请求
POST一个多部分编码(Multipart-Encoded)的文件
响应状态码
响应头
Cookie
重定向与请求历史
超时
错误与异常
正则表达式(regex)
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
许多程序设计语言都支持利用正则表达式进行字符串操作。
XPath
XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言。它最初是用来搜寻XML文档的,但它同样适用于HTML文档的搜索。
XPath语法大致分为三类:
- 层级:
/
选取直接子结点、//
选取子孙结点 - 属性:
@
选取属性 - 函数:
contains(属性名称, 属性值)
、text()
等
菜鸟教程:https://www.runoob.com/xpath/xpath-tutorial.html
BeautifulSoup
解析器
BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, "html.parser") | Python的内置标准库 执行速度适中 文档容错能力强 |
Python 2.7.3 及 3.2.2前的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, "lxml") | 速度快 文档容错能力强 |
需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, ["lxml", "xml"]) BeautifulSoup(markup, "xml") |
速度快 唯一支持XML的解析器 |
需要安装C语言库 |
html5lib | BeautifulSoup(markup, "html5lib") | 最好的容错性 以浏览器的方式解析文档 生成HTML5格式的文档 |
速度慢 不依赖外部扩展 |
节点选择器
方法选择器
-
find_all()
-
根据节点名查询(name属性)
soup.find_all(name="li")
-
根据属性查询(attrs属性)
soup.find_all(attrs={'class': 'item-0'})
-
匹配节点内的文本(text属性)
soup.find_all(text=re.compile(r'hello'))
-
-
find()
find()与find_all()类似,只不过find()返回的是单个元素(第一个匹配的元素),而find_all()分会的是所有匹配元素组成的列表。
CSS选择器
select()方法
例如:
soup.select('ul li') # 选择所有ul节点下面的所有li节点
soup.select('#list-1 .element') # 选择id为list-1的节点下类为element的所有节点
数据存储
文件存储
关系型数据库存储
非关系型数据库存储
Ajax数据爬取
动态渲染页面爬取
Selenium的使用
需要安装Chrome浏览器,并配置好ChromeDriver。(不同浏览器的Driver不同)
-
声明浏览器对象
from selenium import webdriver browser = webdriver.Chrome() # 完成浏览器的初始化
-
访问页面
browser.get("https://www.taobao.com") print(browser.page_source) browser.close()
-
查找节点
Selenium可以驱动浏览器完成各种操作,比如填充表单、模拟点击等。
比如,我们想要向某个输入框输入文字,这就需要知道这个输入框在哪里。
我们可以用Selenium提供的一系列查找节点的方法来获取想要的节点。-
单个节点
from selenium import webdriver browser = webdriver.Chrome() # 完成浏览器的初始化 browser.get("https://www.taobao.com") input_first = browser.find_element_by_id('q') input_second = browser.find_element_by_css_selector('#q') input_third = browser.find_element_by_xpath('//*[@id="q"]') browser.close()
分别根据id、css选择器、XPath来获取输入框节点。
它们返回的结果完全一致。(返回类型为WebElement)
以下是所有获取单个节点的方法:
find_element_by_id()——按id查找
find_element_by_name()——按name值查找
find_element_by_class_name()——按类名查找
find_element_by_tag_name()——按标签名查找
find_element_by_link_text()——此种方法是专门用来定位文本链接的,比如百度首页右上角有“新闻”,“hao123”,“地图”等链接。如:
# 通过link定位"新闻"这个链接并点击 driver.find_element_by_link_text('新闻').click()
find_element_by_partial_link_text()——按部分文本链接名称查找
有时候一个超链接的文本很长很长,我们如果全部输入,既麻烦,又显得代码很不美观,这时候我们就可以只截取一部分字符串,用这种方法模糊匹配了。
find_element_by_xpath()——按xpath方式查找
find_element_by_css_selector()——按css选择器查找
通用方法:
from selenium import webdriver from selenium.webdriver.common.by import By browser.find_element(By.ID, 'q') # 等价于browser.find_element_by_id('q')
-
多个节点
如果查找的目标在网页中只有一个,那么完全可以使用find_element()方法。
但如果有多个节点,就需要使用find_elements()方法。(find_element()方法只能得到第一个节点)
比如,要查找淘宝左侧导航条的所有条目。
from selenium import webdriver browser = webdriver.Chrome() browser.get("https://www.taobao.com/") lis = browser.find_elements_by_css_selector('.service-bd li') print(lis) browser.close()
得到的结果是一个列表,列表中每个元素都是WebElement类型。
通用方法:
from selenium import webdriver from selenium.webdriver.common.by import By browser.find_elements(By.CSS_SELECTOR, '.service-bd li')
-
-
节点交互
Selenium可以驱动浏览器执行一些操作(模拟执行一些动作)。
比较常见的用法有:输入文字时用send_keys()方法,清空文字时用clear()方法,点击按钮时用click()方法。
示例:
from selenium import webdriver import time browser = webdriver.Chrome() browser.get('https://www.taobao.com') input = browser.find_element_by_id('q') input.send_keys('输入测试') time.sleep(1) input.clear() input.send_keys('计算机系统结构') button = browser.find_element_by_class_name('btn-search') button.click()
-
动作链
还有另外一些操作,它们没有特定的执行对象,比如鼠标拖曳操作、键盘按键等,这些动作用另一种方式来执行,那就是动作链。
比如,实现一个节点的拖曳操作,将某个节点从一处拖曳到另一处:
from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) # webDriver只能在一个页面上对元素识别和定位,对于frame/iframe表单内嵌页面上的元素无法直接定位, # 此时就需要通过switch_to.frame()方法将当前定位的主题切换为iframe表单的内嵌页面中。 browser.switch_to.frame('iframeResult') source = browser.find_element_by_css_selector('#draggable') target = browser.find_element_by_css_selector('#droppable') actions = ActionChains(browser) actions.drag_and_drop(source, target) actions.perform()
-
执行JavaScript
from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.zhihu.com/explore') driver.execute_script('window.scrollTo(0, document.body.scrollHeight)') driver.execute_script('window.alert("To Bottom!")') driver.execute_script('window.scrollTo(0, 0)') driver.execute_script('window.alert("To Top!")')
-
获取节点信息
-
获取属性
from selenium import webdriver driver = webdriver.Chrome() url = 'https://maoyan.com/board/4' driver.get(url) logo = driver.find_element_by_css_selector('.logo') print(logo) print(logo.get_attribute('href')) # 获取属性 input = driver.find_element_by_xpath('//ul[@class="navbar"]/li[5]/a') print(input.text) # 获取文本值 榜单 print(input.id) # 获取id print(input.location) # 获取节点在页面中的相对位置 {'x': 500, 'y': 0} print(input.tag_name) # 获取标签名称 a print(input.size) # 获取节点的大小 {'height': 80, 'width': 70}
-
获取文本值
-
- 获取id、位置、标签名、大小
-
切换Frame
webdriver只能在一个页面上对元素识别和定位,对于frame/iframe表单内嵌页面上的元素无法直接定位,此时就需要通过switch_to.frame()方法将当前定位的主题切换为iframe表单
的内嵌页面中,然后再进行操作。 -
延时等待
在Selenium中,get()方法会在网页框架加载结束后结束执行,此时如果获取page_source,可能并不是浏览器完全加载完成的页面,如果某些页面有额外的Ajax请求,我们在网页源代码中也不一定能成功获取到。所有,这里需要延时等待一定时间,确保节点已经加载出来。
-
隐式等待(implicitlyWait)
使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。默认等待时间是0。
from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(10) # 若没有找到,等待10秒 driver.get('https://maoyan.com/board/4') input = driver.find_element_by_name('kw') print(input.get_attribute('placeholder'))
-
显式等待(explicitlyWait)
显示等待方法,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果在规定时间内依然没有加载出该节点,则抛出超时异常。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() driver.get('https://www.taobao.com/') wait = WebDriverWait(driver, 10) # 构造WebDriverWait对象,指定最长等待时间 input = wait.until(EC.presence_of_element_located((By.ID, 'q'))) # 调用until()方法,传入等待条件 # 等待条件EC.presence_of_element_located()的参数是一个定位元组。在这里就是(By.ID, 'q')。 button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search'))) print(input) print(button)
-
-
前进和后退
浏览器都有前进和后退功能,Selenium也可以完成这个操作。
import time from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.baidu.com/') time.sleep(1) driver.get('https://www.taobao.com/') time.sleep(1) driver.back() # 后退 time.sleep(1) driver.forward() # 前进 time.sleep(1) driver.close()
-
Cookies
使用Selenium,可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。
from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.zhihu.com/explore') print(driver.get_cookies()) # 获取所有Cookies driver.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'tky'}) # 添加一个Cookie print(driver.get_cookies()) driver.delete_all_cookies() # 删除所有Cookies print(driver.get_cookies())
-
选项卡管理
访问网页时,我们会在浏览器中开启许多选项卡。在Selenium中,我们也可以对选项卡进行操作。
from selenium import webdriver import time driver = webdriver.Chrome() driver.get('https://www.baidu.com/') driver.execute_script('window.open()') # 执行JS语句,在浏览器中新开启一个选项卡 print(driver.window_handles) # ['CDwindow-898EEA6DCA8AEB5EE82142D437460125', 'CDwindow-40C26092B29F727874D18E7662C901E6'] driver.switch_to.window(driver.window_handles[1]) # 切换到第二个选项卡 driver.get('https://www.taobao.com/') # 第二个选项卡跳转到淘宝 time.sleep(1) driver.switch_to.window(driver.window_handles[0]) # 切换到第一个选项卡 driver.get('https://www.bilibili.com/') # 第一个选项卡跳转到b站
-
异常处理
结尾
全文完。
学习资料:
Python 3网络爬虫开发实战 (崔庆才著)