使用selenium和phantomjs解决爬虫中对渲染页面的爬取

selenium+phantomjs,headerlesschrome

一.selenium+phantomjs

1.selenium是什么:是一个浏览器的自动化测试框架,通过selenium可以写代码,通过运行代码,可以让谷歌浏览器做自动化的工作。

实现:

1.安装:pip install selenium

演示:操作谷歌浏览器,其实操作的是谷歌浏览器的驱动,由驱动来驱动浏览器,既然这样,先下载驱动.(要下载对应版本的驱动)

谷歌驱动下载地址
http://chromedriver.storage.googleapis.com/index.html
浏览器的方法
http://blog.csdn.net/huilan_same/article/details/51896672
浏览器的方法
find_element_by_id   根据id查找指定的对象     
find_elements_by_name   根据name查找
find_elements_by_xpath   根据xpath查找 
find_elements_by_tag_name   根据标签名称进行查找
find_elements_by_class_name    根据类名进行查找
find_elements_by_css_selector  根据选择器进行查找
find_elements_by_link_text      根据a链接的内容进行查找

实例:

from selenium import webdriver    英[səˈli:niəm]

import time

#根据谷歌驱动,创建谷歌浏览器对象
path = r'C:\Users\Administrator\Downloads\chromedriver.exe'
browser = webdriver.Chrome(path)

#打开百度
firsturl = 'http://www.baidu.com/'
browser.get(firsturl)
time.sleep(2)
# 查找输入框
myinput = browser.find_element_by_id('kw')
#向框里面写内容
myinput.send_keys('周杰伦')
time.sleep(3)
#查找点击一下按钮
button =browser.find_element_by_id('su')
button.click()
time.sleep(5)

#查找周杰伦百度百科
#注意:按内容查找必须是a链接的完整文本内容才可以
baike=browser.find_elements_by_link_text('周杰伦_百度百科')[0]
baike.click()
time.sleep(5)

#退出浏览器
browser.quit()

2.phantomjs
phantomjs是什么,是一款浏览器,是无界面的浏览器,它的设计本质不是用来上网的,既然是浏览器,就有浏览器的功能。就可以解释html,css,js,在爬虫的过程中,经常会有这种反爬机制:html是动态加载的,因为js的dom操作,可以动态的给网页添加和删除内容,遇到DOM,如何解决:

(1)捕获接口,从接口解析数据.

(2)通过phantomjs爬取(大招)(效率不高).

专业图片网站:防盗链(meizitu)
还有一种反爬机制:懒加载技术

真正上网的时候,会遇到滚动条加载,这种网站信息难以捕获

可以通过phantomjs模拟滚动条滚动到底部

from selenium import webdriver
import time

# 找到phantomjs路径
path = r'E:\phantomjs\phantomjs-2.1.1-windows\bin\phantomjs.exe'2.1.1-windows\bin\phantomjs.exe'
# 创建浏览器对象
browser = webdriver.PhantomJS(path)

browser.get('http://www.baidu.com/')
time.sleep(2)
# 拍照片的方式
browser.save_screenshot(r'phantomjs\baidu1.png')

# 往下要执行的操作,就是走一步拍一步的过程
browser.find_element_by_id('kw').send_keys('美女')
browser.find_element_by_id('su').click()

time.sleep(2)
browser.save_screenshot(r'phantomjs\baidu2.png')

browser.quit()

滚动到底部

from selenium import webdriver
import time

# 找到phantomjs路径
path = r'C:\Users\zbli\Desktop\1803\day07\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
# 创建浏览器对象
browser = webdriver.PhantomJS(path)

browser.get('https://movie.douban.com/typerank?type_name=%E5%8A%A8%E4%BD%9C&type=5&interval_id=100:90&action=')

time.sleep(2)
browser.save_screenshot(r'phantomjs\douban1.png')

# 模拟滚动条滚动到底部
js = 'document.body.scrollTop=10000'
browser.execute_script(js)
time.sleep(3)

browser.save_screenshot(r'phantomjs\douban2.png')

browser.quit()

(3)懒加载技术(sc.chinaz.com)

div/a/img/@src

但是这样写遇到懒加载反爬获取到的是一个空列表

解决方式:div/a/img/@src2 此时才能找到希望获取到的链接

为啥改变链接名称就可以找到呢:

为什么引入懒加载:

​ 给你一个网页,假如网页中有一百个图片,请问这个网页呈现在你面前,一共向服务器发送了多少次请求(17个requests)

一个·js,一个html都是一个请求,所以如果是100个图片,则有101次请求,没必要把不显示的图片显示在用户面前(只在可视区内显示),不显示的地方如果你往下拉,再才会显示其他图片。这就是懒加载的机制

如何实现:所以的图片img标签里面不写src属性,写src2属性,但是此时src2仅仅是为了保存图片路径,没有其他意义。然后通过js的监听,当图片出现在可视区的时候,通过js动态的将src2属性改成src,所以图片才会顺利的呈现出来。每一个图片都是一个请求,为了只显示可视区内的图片。

以后但凡遇到:src2,data-src,class==lazy等,就是懒加载机制

phantomjs就是一款浏览器,肯定可以执行js,我们要查看执行之后的网页代码

from selenium import webdriver
import time

# 找到phantomjs路径
path = r'C:\Users\zbli\Desktop\1803\day07\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
# 创建浏览器对象
browser = webdriver.PhantomJS(path)

browser.get('http://sc.chinaz.com/tupian/fengjingtupian.html')
time.sleep(2)
browser.save_screenshot(r'phantomjs\tupian1.png')

js = 'document.body.scrollTop=10000'
browser.execute_script(js)
time.sleep(3)
browser.save_screenshot(r'phantomjs\tupian2.png')

# 保存执行js之后的网页源码
with open('tupian.html', 'w', encoding='utf8') as fp:
    fp.write(browser.page_source)

browser.quit()

二.headlesschrome是什么

定义:没有头部的谷歌浏览器,无界面的谷歌浏览器。正是由于谷歌有了无界面的浏览器,所以phantomjs就倒闭了, 不再维护了,尽量使用无界面的谷歌浏览器。

要求:如果是linux,谷歌浏览器要求版本在59+以上,windows要求60+以上

使用:

from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

谷歌无界面模式

#操作无界面谷歌
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

#让谷歌浏览器以无界面模式启动
path = r'C:\Users\Administrator\Downloads\chromedriver.exe'
browser = webdriver.Chrome(path,chrome_options=chrome_options)
browser.get('http://www.baidu.com')
time.sleep(2)
browser.save_screenshot(r"C:\Users\Administrator\Desktop\chrome.png")

#以后的操作和phantomjs同理

browser.quit()

三.模拟登陆

原理介绍:

(1)http协议特性,(无状态协议),服务器一直在监听浏览器发的请求,得到响应,请求与响应过程称为一次交互,两次请求都是不同的请求,没有任何关系,问题出现:身份问题(登陆问题),当登陆成功了,服务器会给你发一个狗牌,在响应的时候将这些信息都写到了浏览器中,下一次浏览器发送请求的的时候带着狗牌过去就可以了

(2)模拟登陆的实现

想通过代码访问登陆后的页面,

1.带着牌过去,牌从哪里来?抓包,抓到浏览器访问的时候的狗牌,将cookie给抓取到,然后写到程序中的headers头部里面(万能)

2.通过代码模拟登陆,模拟发送post即可。

实例:登陆有验证码的古诗文网

验证码下载到本地,让用户手动输

from bs4 import BeautifulSoup
import requests
import urllib.request

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}

def download_image(s):
    url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'

    r = s.get(url=url, headers=headers)
    # 解析内容,得到验证码图片的src属性
    soup = BeautifulSoup(r.text, 'lxml')
    image_src = 'https://so.gushiwen.org' + soup.find('img', id='imgCode')['src']
    # 将图片下载到本地
    # urllib.request.urlretrieve(image_src, 'code.png')
    r = s.get(url=image_src, headers=headers)
    with open('code.png', 'wb') as fp:
        fp.write(r.content)


    # 获取表单里隐藏的数据
    view_state = soup.find('input', id='__VIEWSTATE')['value']
    view_gen = soup.find('input', id='__VIEWSTATEGENERATOR')['value']
    return view_state, view_gen

def moni_post(s, view_state, view_gen):
    # post的地址
    post_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
    code = input('请输入验证码:')
    # 表单数据
    formdata = {
        '__VIEWSTATE': view_state,
        '__VIEWSTATEGENERATOR': view_gen,
        'from': 'http://so.gushiwen.org/user/collect.aspx',
        'email': '[email protected]',
        'pwd': '123456',
        'code': code,
        'denglu': '登录',
    }
    r = s.post(url=post_url, headers=headers, data=formdata)

    # 将响应内容写入到文件中
    with open('deng.html', 'wb') as fp:
        fp.write(r.content)

def main():
    # 首先创建一个会话,然后后续的操作都通过这个会话进行,这样就可以保证都是同一个会话了
    s = requests.Session()
    # 下载验证码到本地
    view_state, view_gen = download_image(s)
    # 模拟登录
    moni_post(s, view_state, view_gen)

if __name__ == '__main__':
    main()

注意:只要是有验证码的一定要通过会话操作,通过Session会话来完成

创建一个会话,然后后续操作都通过会话进行,保证在同一次会话当中

s=requests.Session

还要获取表单里面隐藏的数据

view_state = soup.find(‘input’,id=)

view_gen=

要将这两个值给返回,因为这两个参数是在表单里面隐藏的,而且登陆的时候重新写入。

四.下载视频 : 短视频

365yg.com 视频下载网站

1.单视频下载

import requests
url = 'http://v11-tt.ixigua.com/1f8fcd093ff8db362348f1ac58c06bec/5b3c86b5/video/m/220c59fd677a39c467798506da24f41a73c1158ad050000077553974abd/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
r = requests.get(url=url, headers=headers)
with open(r'shipin/123我爱你.mp4', 'wb') as fp:
    fp.write(r.content)

print('下载成功')

2.多视频下载:

import requests
import time
from bs4 import BeautifulSoup
import json
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}

def get_video_detail():
    '''
    url = 'http://365yg.com/'
    r = requests.get(url=url, headers=headers)
    with open('jinri.html', 'wb') as fp:
        fp.write(r.content)
    exit()
    # 解析之
    soup = BeautifulSoup(r.text, 'lxml')
    # 提取所有视频页链接
    a_list = soup.find_all('a', class_='link')
    print(a_list)
    print(len(a_list))
    '''

    # 抓包捕获接口
    url = 'http://365yg.com/api/pc/feed/?min_behot_time=0&category=video_new&utm_source=toutiao&widen=1&tadrequire=true&as=A1051B43DC57D41&cp=5B3C87BD8401AE1&_signature=XdHlThAcBu4K5q0VubnD.l3R5V'
    # 接口中的widen可以理解为分页,是2的时候就是第二页,以此类推
    r = requests.get(url=url, headers=headers)
    # 将json格式字符串转化为python对象
    obj = json.loads(r.text)
    # 得到包含所有视频的列表, 该列表中存放的都是字典
    data_list = obj['data']
    # 遍历列表,获取字典里面的source_url属性
    video_detail_list = []
    for data in data_list:
        detail_url = 'http://365yg.com' + data['source_url']
        video_detail_list.append(detail_url)

    return video_detail_list

def download(video_detail_list, browser):
    i = 0
    # 遍历列表,依次发送请求即可
    for detail_url in video_detail_list:
        '''
        r = requests.get(url=detail_url, headers=headers)
        # 生成soup对象,查找video标签,获取src属性即可
        soup = BeautifulSoup(r.text, 'lxml')
        with open('detail.html', 'wb') as fp:
            fp.write(r.content)
        # video = soup.find('video')

        # print(video)
        exit()
        '''
        i += 1
        browser.get(detail_url)
        time.sleep(5)
        soup = BeautifulSoup(browser.page_source, 'lxml')
        video_src = 'http:' + soup.find('video')['src']
        # print(video_src)
        # exit()
        r = requests.get(url=video_src, headers=headers)
        filepath = './shipin/' + str(i) + '.mp4'
        print('正在下载%s......' % filepath)
        with open(filepath, 'wb') as fp:
            fp.write(r.content)

        print('结束下载%s' % filepath)
        time.sleep(2)


def main():
    # 让谷歌浏览器以无界面模式启动
    path = r'C:\Users\zbli\Desktop\1803\day07\ziliao\chromedriver.exe'
    browser = webdriver.Chrome(path, chrome_options=chrome_options)
    # 获取到所有的视频页的链接
    video_detail_list = get_video_detail()
    # 向每一个详情页发送请求,解析内容,得到视频的src,然后下载即可
    download(video_detail_list, browser)

    browser.quit()

if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/lj1029351265/article/details/81369875