昨日内容回顾
-
二手房数据局部查找
今日再独立完成代码编写 代码函数封装
-
爬取天气数据
有时候页面上的数据是通过js代码动态加载的 需要我们通过浏览器检测请求代码 network 查找js代码请求的url地址 """ 有一类url我们在发送请求的时候不会给我们返回一个HTML页面 而是一些json格式的数据 这种类型的url我们习惯称之为>>>:接口 """
-
爬取新闻数据
网页的HTML中参杂了干扰项需要我们通过if判断筛选避免 针对分页 针对新闻详情页如何爬取
-
自动化测试工具
selenium模块 下载 浏览器驱动(千万不要忘了) 针对不同的浏览器需要下载不同的驱动文件 默认推荐使用谷歌浏览器和谷歌驱动
今日内容概要
- selenium基本操作
- selenium选择器
- Xpath选择器(使用频率甚至有时候比css选择器还高)
- selenium补充操作
- 爬取某东指定商品信息
- 其他防爬措施补充
- 爬取贴吧图片数据
今日内容详细
selenium选择器
1、find_element_by_id 根据id找
print(bro.find_element_by_id('s-top-left'))
2、find_element_by_link_text 根据链接名字找到控件(a标签的文字)
print(bro.find_element_by_link_text('直播'))
3、find_element_by_partial_link_text 根据链接名字找到控件(a标签的文字)模糊查询
print(bro.find_element_by_link_text('播')) # select * from userinfo where name like '%jason%'
4、find_element_by_tag_name 根据标签名
print(bro.find_element_by_tag_name('div'))
5、find_element_by_class_name 根据类名
print(bro.find_element_by_class_name('c1'))
6、find_element_by_name 根据属性名
print(bro.find_element_by_name('username'))
7、find_element_by_css_selector 根据css选择器
print(bro.find_element_by_css_selector('#d1>span'))
小练习
控制浏览器自动打开京东
并在商品搜索栏中自动填写手机并搜索
页面停留十秒钟之后自动关闭
from selenium import webdriver
import time
# 控制谷歌浏览器
bro=webdriver.Chrome()
# 明确目标网站和请求方式
bro.get("http://www.jd.com")
# 查找搜索框标签
inputEle = bro.find_element_by_id('key')
# 在标签内填写文本
inputEle.send_keys('衣服')
# 查找搜索款按钮 或者直接模拟键盘的enter键
# btnEle = bro.find_element_by_css_selector('.form button')
# 点击按钮
# btnEle.click()
from selenium.webdriver.common.keys import Keys # 键盘按键操作
inputEle.send_keys(Keys.ENTER)
# 停留十秒
time.sleep(10)
# 关闭浏览器页面
bro.close()
课堂练习
1.自动打开百度并搜索数据分析
from selenium import webdriver
import time
# 控制谷歌浏览器
bro=webdriver.Chrome()
# 明确目标网站和请求方式
bro.get("http://www.baidu.com")
# 查找搜索框标签
inputEle = bro.find_element_by_id('kw')
inputEle.send_keys('美女')
from selenium.webdriver.common.keys import Keys
inputEle.send_keys(Keys.ENTER) # 按下键盘的enter键
time.sleep(5)
bro.close()
2.自动打开百度并点击登录 弹出款中在点击用户名登录
并自动输入用户名和密码登录
from selenium import webdriver
import time
# 控制谷歌浏览器
bro=webdriver.Chrome()
# 明确目标网站和请求方式
bro.get("http://www.baidu.com")
bro.implicitly_wait(10)
aEle = bro.find_element_by_link_text('登录')
aEle.click()
pEle= bro.find_element_by_id('TANGRAM__PSP_11__footerULoginBtn')
pEle.click()
userEle = bro.find_element_by_id('TANGRAM__PSP_11__userName')
userEle.send_keys('jason')
pwdEle = bro.find_element_by_id('TANGRAM__PSP_11__password')
pwdEle.send_keys('jason666')
btnEle = bro.find_element_by_id('TANGRAM__PSP_11__submit')
btnEle.click()
等待问题
'''
有很多网页在加载的时候速度可能会笔记慢 而代码的执行速度是非常快的
如果代码以及执行到一个标签的查找而页面还没有加载处理则可能会导致报错
可以使用下述方式避免
'''
# 显示等待和隐示等待
# 隐式等待:在查找所有元素时,如果尚未被加载,则等10秒
browser.implicitly_wait(10) # 表示等待所有
# 显式等待:显式地等待某个元素被加载(不推荐使用)
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))
Xpath选择器
功能也是为了更加方便快捷的查找标签
是所有选择器当中功能最为强大的一个
# 效率很高 使用广泛
doc='''
<html>
<head>
<base href='http://example.com/' />
<title>Example website</title>
</head>
<body>
<div id='images'>
<a href='image1.html' a="xxx">Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
<a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
<a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
<a href='image4.html' class='li'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
<a href='image5.html' class='li li-item' name='items'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
<a href='image6.html' name='items'><span><h5>test</h5></span>Name: My image 6 <br /><img src='image6_thumb.jpg' /></a>
</div>
</body>
</html>
'''
from lxml import etree
html=etree.HTML(doc)
# html=etree.parse('search.html',etree.HTMLParser())
# 1 所有节点
# a=html.xpath('//*') #匹配所有标签
# 2 指定节点(结果为列表)
# a=html.xpath('//head')
# 3 子节点
'''一个斜杠是儿子 两个斜杠是后代'''
# a=html.xpath('//div/a')
# a=html.xpath('//body/a') #无数据
# a=html.xpath('//body//a') # 子孙节点
# 4 父节点
# a=html.xpath('//body//a[@href="image1.html"]') # 找body内部所有href属性等于image1.html的后代a标签
# a=html.xpath('//body//a[@href="image1.html"]/..')
'''.表示当前层级 ..表示上一次'''
# a=html.xpath('//body//a[1]/..') #从1开始 # 找body内部所有的后代a标签的第一个a
# 也可以这样
# a=html.xpath('//body//a[1]/parent::*')
# 5 属性匹配
# a=html.xpath('//body//a[@href="image1.html"]')
# 6 文本获取
# a=html.xpath('//body//a[@href="image1.html"]/text()')
# a=html.xpath('//body//a/text()')
# 7 属性获取
# a=html.xpath('//body//a/@href')
# # 注意从1 开始取(不是从0开始)
# a=html.xpath('//body//a[2]/@href')
# 8 属性多值匹配
# a 标签有多个class类,直接匹配就不可以了,需要用contains
# a=html.xpath('//body//a[@class="li"]')
# a=html.xpath('//body//a[contains(@class,"li")]/text()')
# 9 多属性匹配
# a=html.xpath('//body//a[contains(@class,"li") or @name="items"]')
# a=html.xpath('//body//a[contains(@class,"li") and @name="items"]/text()')
# 10 按序选择
# a=html.xpath('//a[2]/text()')
# a=html.xpath('//a[2]/@href')
# 取最后一个
# a=html.xpath('//a[last()]/@href')
# 位置小于3的
# a=html.xpath('//a[position()<3]/@href')
# 倒数第二个
# a=html.xpath('//a[last()-2]/@href')
# 11 节点轴选择
# ancestor:祖先节点
# 使用了* 获取所有祖先节点
# a=html.xpath('//a/ancestor::*')
# # 获取祖先节点中的div
# a=html.xpath('//a/ancestor::div')
# attribute:属性值
# a=html.xpath('//a[1]/attribute::*')
# child:直接子节点
# a=html.xpath('//a[1]/child::*')
# descendant:所有子孙节点
# a=html.xpath('//a[6]/descendant::*')
# following:当前节点之后所有节点
# a=html.xpath('//a[1]/following::*')
# a=html.xpath('//a[1]/following::*[1]/@href')
# following-sibling:当前节点之后同级节点
# a=html.xpath('//a[1]/following-sibling::*')
# a=html.xpath('//a[1]/following-sibling::a')
# a=html.xpath('//a[1]/following-sibling::*[2]/text()')
# a=html.xpath('//a[1]/following-sibling::*[2]/@href')
print(a)
其他方法
.click()
.clear()
.send_keys()
.send_keys(键盘动作)
#获取属性:
tag.get_attribute('src')
#获取文本内容
tag.text
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)
...
爬取商品信息
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
# 控制谷歌浏览器
bro=webdriver.Chrome()
# 明确目标网站和请求方式
bro.get("http://www.jd.com")
bro.implicitly_wait(10)
# 获取用户想要搜索的商品名称
# targetGood = input('请输入您想要爬取的商品名称>>>:').strip()
targetGood = '手机' # 先固定写法 方便测试
# 查找商品搜索款 填写内容
btnEle = bro.find_element_by_id('key')
btnEle.send_keys(targetGood)
btnEle.send_keys(Keys.ENTER)
# 进入商品详情页 爬取数据
# 先查找所有的li标签
li_list = bro.find_elements_by_class_name('gl-item')
"""
注意 bro.find_element有加不加s之分
不加s表示查找单个元素
加s表示查找所有元素
"""
for li in li_list:
img = li.find_element_by_css_selector('.p-img a img')
'''图片的路径有时候在src中有时候在data-lazy-img中'''
img_src = img.get_attribute('src')
if not img_src:
img_src = 'https:' + img.get_attribute('data-lazy-img')
link = li.find_element_by_css_selector('.p-img a').get_attribute('href')
price = li.find_element_by_css_selector('.p-price i').text
name = li.find_element_by_css_selector('.p-name em').text.replace('\n', '')
commit = li.find_element_by_css_selector('.p-commit a').text
print('''
商品链接:%s
商品图片:%s
商品简介:%s
商品价格:%s
商品销量:%s
''' % (link, img_src, name, price, commit))
# 京东商品的评论数就是销量
作业
1.思考如何爬取多页
查找下一页标签点击
或者研究url规律
2.封装成函数版本