pyhton+selenuim实现自动化网络爬虫

之前有个需求,需要从网上爬取数据,爬虫的话利用python很容易做,但是该网站需要账号密码登陆,所以采用了python+selenuim来实现,中间还是有不少坑的,尤其在linux上部署的时候。

selenuim帮我们实现了模拟打开浏览器、输入账号密码并登陆,后面获取数据就通过解析网页html来实现。

先上代码吧:

# -*- coding: utf-8 -*-

from selenium.webdriver.chrome.options import Options
from date import get_yesterday
from selenium import webdriver
import time
from bs4 import BeautifulSoup
import json
from pyvirtualdisplay import Display

#linux上无可视化环境下,模拟可视化环境
display = Display(visible=0, size=(800, 600))
display.start()
service_args = []
service_args.append('--load-images=no')  ##关闭图片加载
service_args.append('--disk-cache=yes')  ##开启缓存
service_args.append('--ignore-ssl-errors=true') ##忽略https错误
service_args.append('--ssl-protocol=TLSv1')

user_name = '****'
password = '****'
#chrome浏览器
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

#fire_fox浏览器
fire_fox_option = webdriver.FirefoxOptions()
fire_fox_option.add_argument('--headless')
fire_fox_option.add_argument('--disable-gpu')
fire_fox_option.add_argument('javascriptEnabled=True')

#browser = webdriver.Chrome(chrome_options=chrome_options)
browser = webdriver.Firefox(executable_path='./geckodriver', firefox_options=fire_fox_option)
yesterday_date = str(get_yesterday())


def gen_url(platform):
    url = ''
    if platform == 'ios':
        url = "https://hq1.appsflyer.com/dashboard/overview/id1307961750#end="\
              + yesterday_date + "&grouping=attribution&start=" + yesterday_date
    elif platform == 'android':
        url = "https://hq1.appsflyer.com/dashboard/overview/com.netease.chiji#end="\
              + yesterday_date + "&grouping=attribution&start=" + yesterday_date
    else:
        print ("Error, platform error, should be ios or android!!!")

    return url


def web_click(url):

    browser.set_page_load_timeout(1200)
    browser.set_script_timeout(1200)
    #解决账号密码登陆
    browser.get('https://hq1.appsflyer.com/auth/login')

    elem = browser.find_element_by_name('username')
    elem.send_keys(user_name)
    elem = browser.find_element_by_name('password')
    elem.send_keys(password)
    elem = browser.find_element_by_id("submit_btn")
    elem.click()
    #网页有大量JavaScript渲染的内容,试了很多方法等待加载完成,最后发现sleep方法效果最好,无语了
    time.sleep(10)

    #browser.switch_to.window(browser.window_handles[-1])
    #加载目标网页的url
    browser.get(url)
    #等待网页加载完成
    time.sleep(30)
    page_source = browser.page_source
    
    return page_source


def analysis_page(page_source, plat_form):
    #采用BeautifulSoup来解析网页
    html = BeautifulSoup(page_source, "html.parser")
    divs = html.find_all("div", attrs={"class": "af-kpi-box-piece"})
    result = {}

    for div in divs:
        key = ''
        value = ''
        hs = div.find_all(["h5", "text", "h2"])
        for h in hs:

            # 系统会自动按照find_all参数的顺序获取值
            if h.name == 'h2' and h.get("class") is None:
                value = h.get_text()

            elif h.name == 'h5' and h.get("class") is None:
                key = h.get_text()

        if (key == 'Non-Organic' or key == 'Organic') and '$' in value:
            key = key.replace('-', '_') + '_Cost'
	    #value = value.replace(',', '')
        elif key == 'Clicks to Installs':
            key = 'Clicks_to_Installs'
        elif '-' in key:
            key = key.replace('-', '_')

        result[key] = value

    result['date'] = yesterday_date
    result['platform'] = plat_form

    with open("./data/" + yesterday_date, 'a') as f:
        f.write(json.dumps(result))
        f.write('\n')

    browser.quit()
    display.stop()

有几个关键点介绍一下:

windows:

  • 使用selenium,下载浏览器的driver,模拟打开浏览器访问的模式效果最好
  • 使用headless,不打开浏览器,无GUI模式运行,效果也很好
  • 使用phantomJS模式,类似无GUI模式,各种问题,各种坑、速度奇慢还拿不到正确结果,而且这个已经不维护了,强烈不建议

linux:

  • 若本身没有GUI,不存在打开浏览器的行为
  • 下载浏览器以及对应的driver,使用selenium的headless或者phantomJS模式
  • 另外还需要下载安装xvfb,模拟显示器。

版本匹配问题:

windows:

  •     一般都是最新的浏览器和对应最新的driver,问题不大

linux:
           目前测试通过的版本:

  •         Mozilla Firefox           52.8.0
  •         selenium                  3.12.0
  •         geckodriver               v0.17.0-linux64

selenium操作等待问题:

由于抓取的网页是由很多JavaScript脚本渲染生成,所以在get和click操作之后都需要预留一定的等待时间后
才能抓取到渲染完成的网页,这边经过测试后统一用time.sleep来解决,效果最好。selenium已经抛弃了phantomJS,可以自身完成phantomJS的功能,建议以后直接使用selenium,无视phantomJS

参考资料:

https://stackoverflow.com/questions/39547598/selenium-common-exceptions-webdriverexception-message-connection-refused
http://blog.51cto.com/casey/1763141

            资源依赖:

  •             windows:
  •             selenuim的driver文件
  •             http浏览器
  •             python依赖包

linux:

  •             selenuim的driver文件
  •             http浏览器
  •             python依赖包
  •             xvfb(无GUI模式)

你可能感兴趣的:(pyhton+selenuim实现自动化网络爬虫)