这里我们使用的是selenium+driver 这个方法通俗的说就是模拟人去百度查找图片,内容比较多,但是很实用,希望大家能看完,必定受益匪浅。
一、知识前提
我们需要了解一些概念1.什么是selenium?
selenium是网页自动化测试工具,可以自动化的操作浏览器。如果需要操作哪个浏览器需要安装对应的driver,比如你需要通过selenium操作chrome,那必须安装chromedriver,而且版本与chrome保持一致。
2、driver
操作浏览器的驱动,分为有界面和无界面的
有界面:与本地安装好的浏览器一致的driver(用户可以直接观看,交互比如单击、输入)
无界面:phantomjs(看不到,只能通过代码操作,加载速度比有界面的要快)
了解完之后,安装selenium:
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
为了让大家对selenium有进一步的了解。细心的博主给大家带来了福利,那就是使用selenium爬取百度妹子图。为了大家不把我当成LSP,我把妹子图片换成了哆啦A梦,希望大家不要叫我LSP!
二、保存内容成html
2.1 通过selenium模拟普通人查找百度图片
1. 普通人搜索图片
2 分析
知道了普通人如何查找图片,那么我们下面就通过selenium模拟上述的具体过程。在模拟之前,我们先分析一下几个主要的点。
1. 输入框
我们通过打开开发者选项,找到输入框所在部分,解析xpath
2. 查询点击
3. 点击关于美女的百度图片
3 代码实现
# 控制chrome浏览器
driver = webdriver.Chrome("./chromedriver/chromedriver.exe")
#窗口最大化
driver.maximize_window()
# 输入网址
driver.get("https://www.baidu.com/")
# 找到文本框,输入文字
driver.find_element_by_xpath('//*[@id="kw"]').send_keys("哆啦a梦图片")
#找到按钮,单击
driver.find_element_by_xpath('//*[@id="su"]').click()
#停一下,等待加载完毕
time.sleep(2)
#找到a标签,单击
driver.find_element_by_xpath('//*[@id="1"]/h3/a').click()
#停一下,等待加载完毕
time.sleep(2)
,我们可以看到已经完美的模拟出来过程。
在这里我们看效果是很不错的,但是其实还是有点小问题的,我们现在其实还只是在第一个窗口中,因此我们需要切换一下的窗口,这个时候我们就需要添加下面一行代码
#切换窗口,因为现在打开了一个窗口,目前还是在第1个窗口中
driver.switch_to.window(driver.window_handles[1])
4 模拟人为鼠标滑轮滚动屏幕
模拟人为鼠标滑轮滚动屏幕,我们有Selenium+python自动化之js屏幕滑动,下列为脚本实现js滑屏
scroll="document.documentElement.scrollTop=800"#垂直滚动 px
scroll = "document.documentElement.scrollLeft=1000"#水平滚动
scroll="window.scrollTo(0,10000)"#滚动到指定坐标
scroll="window.scrollBy(0,100)"#滑动到相对坐标
scroll="window.scrollTo(0,document.body.scrollHeight)"#获取body的高度,滑到底部
document.body.scrollWidth 获取body宽度
driver.execute_script(scroll)
在此,我使用了滑动到指定坐标。由于已经验证过了,所以直接给出正确游标
window.scrollTo(0,10000)
效果图如下:
在此,我先测试翻页10次,代码如下
for i in range(10):
#执行js
driver.execute_script("window.scrollTo(0,10000)")
time.sleep(1)
效果图:
好了,所有的准备工作,我们已经完成了。那么接下来我们只需把他保存为html页面即可。
2.2 此部分完整代码
from selenium import webdriver
from lxml import etree
import os
import time
import requests
import re
import random
#
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
#创建文件夹
if not os.path.exists("./files/baidu"):
os.makedirs("./files/baidu")
def get_html():
# 控制chrome浏览器
driver = webdriver.Chrome("./chromedriver/chromedriver.exe")
#窗口最大化
driver.maximize_window()
# 输入网址
driver.get("https://www.baidu.com/")
# 找到文本框,输入文字
driver.find_element_by_xpath('//*[@id="kw"]').send_keys("哆啦a梦图片")
#找到按钮,单击
driver.find_element_by_xpath('//*[@id="su"]').click()
#停一下,等待加载完毕
time.sleep(2)
#找到a标签,单击
driver.find_element_by_xpath('//*[@id="1"]/h3/a').click()
#停一下,等待加载完毕
time.sleep(2)
#切换窗口,因为现在打开了一个窗口,目前还是在第1个窗口中
driver.switch_to.window(driver.window_handles[1])
for i in range(10):
#执行js
driver.execute_script("window.scrollTo(0,10000)")
time.sleep(1)
#获取页面html
html = driver.page_source
# 关闭
driver.quit()
#保存html
with open("baidu.html","w",encoding="utf-8") as file:
file.write(html)
return html
if __name__ == '__main__':
get_html()
2.3 保存HTML并查看是否保存成功
到这里,我们的保存工作就已经完成了,下面就需要对其进行解析了。
三、解析图片链接
3.1 前期分析
在此先给出所以能够爬取的图片URL,然后进行分析,如何得到
data-objurl="http://pic.jj20.com/up/allimg/1113/041620103S8/200416103S8-4-1200.jpg"
data-imgurl="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1948216838,2050876637&fm=26&gp=0.jpg">
"hoverURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1948216838,2050876637&fm=26&gp=0.jpg"
"thumbURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1672252528,4061027335&fm=26&gp=0.jpg"
"middleURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1672252528,4061027335&fm=26&gp=0.jpg"
我们首先先把得到的html打印出来,然后通过查找URL,找到图片的URL即可
由于本次只以此两个URL为例,所以其他的都不在自行查找了。
,正是我们所需要的图片,下面就可以开始提取了。
3.2 正则提取URL
#读数据
with open("baidu.html", "r", encoding="utf-8") as file:
html = file.read()
#通过正则获取img url
img_list1 = re.findall(r'data-objurl="(.*?)"', html)
img_list2 = re.findall(r'data-imgurl="(.*?)"', html)
#合并
img_list1.extend(img_list2)
print(img_list2)
现在我们先打开URL,看看能不能打开。
结果我们发现有的URL并不能打开,这是正常的,因为各种原因总会有某些URL无法打开,这时候我们先多找几个URL试验即可。
但是直接这样看的话,并不好看,这个时候我们需要把他遍历并打印所有的URL
#替换部分不需要的字符
img_list = map(lambda x:x.replace("amp;",""),img_list1)
#遍历
for img in img_list:
print(img)
time.sleep(random.random()*3)
然后查看结果
,到这里我们所有需要分析的部分都已经分析完成了。
四、完整代码
# encoding: utf-8
'''
2020最新python学习资源分享:1156465813
'''
from selenium import webdriver
from lxml import etree
import os
import time
import requests
import re
import random
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
#创建文件夹
if not os.path.exists("./files/baidu"):
os.makedirs("./files/baidu")
def get_html():
# 控制chrome浏览器
driver = webdriver.Chrome("./chromedriver/chromedriver.exe")
#窗口最大化
driver.maximize_window()
# 输入网址
driver.get("https://www.baidu.com/")
# 找到文本框,输入文字
driver.find_element_by_xpath('//*[@id="kw"]').send_keys("美女")
#找到按钮,单击
driver.find_element_by_xpath('//*[@id="su"]').click()
#停一下,等待加载完毕
time.sleep(2)
#找到a标签,单击
driver.find_element_by_xpath('//*[@id="1"]/h3/a').click()
#停一下,等待加载完毕
time.sleep(2)
#切换窗口,因为现在打开了一个窗口,目前还是在第1个窗口中
driver.switch_to.window(driver.window_handles[1])
for i in range(10):
#执行js
driver.execute_script("window.scrollTo(0,10000)")
time.sleep(1)
#获取页面html
html = driver.page_source
# 关闭
driver.quit()
#保存html
with open("baidu.html","w",encoding="utf-8") as file:
file.write(html)
return html
def get_data():
#读数据
with open("baidu.html", "r", encoding="utf-8") as file:
html = file.read()
#通过正则获取img url
img_list1 = re.findall(r'data-objurl="(.*?)"', html)
img_list2 = re.findall(r'data-imgurl="(.*?)"', html)
#合并
img_list1.extend(img_list2)
#替换部分不需要的字符
img_list = map(lambda x:x.replace("amp;",""),img_list1)
#遍历
for img in img_list:
print(img)
time.sleep(random.random()*3)
#获取图片字节,可能被拦截,加上代理ip
content = requests.get(img,headers=headers).content
#文件的名字
filename = "./files/baidu/{}".format(img.split("/")[-1])
#文件写
with open(filename,"wb") as file:
file.write(content)
if __name__ == '__main__':
get_html()
get_data()
# data-objurl="http://pic.jj20.com/up/allimg/1113/041620103S8/200416103S8-4-1200.jpg"
# data-imgurl="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1948216838,2050876637&fm=26&gp=0.jpg">
# "hoverURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1948216838,2050876637&fm=26&gp=0.jpg"
# "thumbURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1672252528,4061027335&fm=26&gp=0.jpg"
# "middleURL":"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1672252528,4061027335&fm=26&gp=0.jpg"
五、爬取结果
但是! 我们这样爬取的话,过一段时间就会被识别出来。如下图:
这个时候,我们最好加上代理IP 。进行循环爬取。
六、修改版源码(加上代理IP)
# encoding: utf-8
'''
2020最新python学习资源分享:1156465813
'''
from selenium import webdriver
from lxml import etree
import os
import time
import requests
import re
import random
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
#创建文件夹
if not os.path.exists("./files/baidu"):
os.makedirs("./files/baidu")
def get_html():
# 控制chrome浏览器
driver = webdriver.Chrome("./chromedriver/chromedriver.exe")
#窗口最大化
driver.maximize_window()
# 输入网址
driver.get("https://www.baidu.com/")
# 找到文本框,输入文字
driver.find_element_by_xpath('//*[@id="kw"]').send_keys("哆啦A梦图片")
#找到按钮,单击
driver.find_element_by_xpath('//*[@id="su"]').click()
#停一下,等待加载完毕
time.sleep(2)
#找到a标签,单击
driver.find_element_by_xpath('//*[@id="1"]/h3/a').click()
#停一下,等待加载完毕
time.sleep(2)
#切换窗口,因为现在打开了一个窗口,目前还是在第1个窗口中
driver.switch_to.window(driver.window_handles[1])
for i in range(10):
#执行js
driver.execute_script("window.scrollTo(0,10000)")
time.sleep(1)
#获取页面html
html = driver.page_source
# 关闭
driver.quit()
#保存html
with open("baidu.html","w",encoding="utf-8") as file:
file.write(html)
return html
def get_proxies():
#这里获取的芝麻HTTP代理http https\\
time.sleep(2+random.random()*3)
proxies = {
"http": "",
"https": ""
}
url = "http://http.tiqu.alicdns.com/getip3?num=1&type=2&pro=&city=0&yys=0&port=11&time=1&ts=0&ys=0&cs=1&lb=1&sb=0&pb=45&mr=1®ions="
response = requests.get(url)
content = response.json()
proxies["https"] = content["data"][0]["ip"]+":"+str(content["data"][0]["port"])
return proxies
def get_content(url):
"""发送请求获取数据"""
#如果报错,停一会,再发,有10次机会,否则返回空字节
for i in range(5):
try:
# 获取图片字节,可能被拦截,加上代理ip
return requests.get(url, headers=headers, proxies=get_proxies()).content
except:
print(url, "失败,尝试第{}次".format(i + 1))
time.sleep(random.random()*5)
return b""
def get_data():
#读数据
with open("baidu.html", "r", encoding="utf-8") as file:
html = file.read()
#通过正则获取img url
img_list1 = re.findall(r'data-objurl="(.*?)"', html)
img_list2 = re.findall(r'data-imgurl="(.*?)"', html)
#合并
img_list1.extend(img_list2)
#替换部分不需要的字符
img_list = map(lambda x:x.replace("amp;",""),img_list1)
#遍历
for img in img_list:
print(img)
content = get_content(url=img)
#文件的名字
filename = "./files/baidu/{}".format(img.split("/")[-1])
#文件写
with open(filename,"wb") as file:
file.write(content)
if __name__ == '__main__':
#get_html()
get_data()
到现在,完整的代码已经完成了,如果爬妹子的图片,在代码里面把哆啦A梦改成妹子就可以了