初谈爬虫之selenium

    大家好,我是隔壁小王~如果你只是一个爬虫 或者python的新手,我相信本文会对于你的学习有一点宏观的引导作用。

    其实我并不是一个专业的python爬虫人员,至今为止,python主要cover的五个方向:云计算,运维,爬虫,web后台,人工智能中,我主要接触的是云计算,运维脚本和web后台这三部分。但是由于最近突发爬虫需求,要2天出结果。。。好吧,2天,从学习到开发到得出数据并进行解析,好吧,这是一个不可能完成的任务,事实上我做的结果也让我自己很不满意。But,重压之下,人的学习速度还是可以的,虽然最后的数据不是很完善,但是也基本完成了一个比较完整的爬虫工程。

    那么我到底要讲什么呢?接下来是重点,做过web的人应该多少对爬虫有了解,毕竟本质上还是涉及网络的:爬虫有很多方法去实现,虽然本质上都是发送请求,但是面对各种网站,各种反扒机制,选择的确是存在的。

    1.urllib系列

    这个方法是一个比较原生的方法,要自己配置cookie、header等,同时还要使用正则,如果你对web的交互比较熟悉,这个库上手应该是easy的。网上很多资料啦,这里不赘述了。

    2.requests

    requests库实际上是urllib2的一种扩充,更加的方便,同在在web开发时候写些测试用例啥的,模仿用户发起请求啥的。所以,也是一种比较原生的爬虫方法,要学爬虫我建议这两个库应该是基础,理解深一点比较好。

    3.scrpy

    很著名的爬虫框架,相比上述两个,这个是最推荐新手使用的方法,帮你把异步爬虫任务处理好,速度快,而且有经验的人会发现:个人写的爬虫代码是很容易的断的,但框架的用户体验会好很多。

    4.干货:selenium

    这是一种比较另类的爬虫方案,这是完全模仿人的行为进行数据获取的方法,所以缺点就是非常非常非常的慢,优点就是针对反扒会比较好。

    网上其实没有很多特别适合新手看的selenium教程,这里讲一些简单易用的方法和概念,通过这个再去扩展思路会清晰一些。

    通过selenium可以直接控制浏览器,浏览器有两种:无界面浏览器(phantomjs)和有界面的(chrome等)。用selenium是需要分析网页的,所以最好用有界面的把。接下来演示下常用的api和效果。

     1)开启一个浏览器

    代码如下:

from selenium import webdriver


if __name__ == '__main__':
    driver = webdriver.Firefox()
    driver.get('www.baidu.com')

       我这里使用的是火狐浏览器,据说是兼容性最好。先通过webdriver构建一个浏览器的控制对象,载入相应的url后,就可以开启浏览器了。


    这样就非常顺利的开了百度网页了,如果这时候有的人报错或者有的人浏览器打开了但是网页没有打开,我想说,请检查你的浏览器版本和selenium的版本,这是大部分情况下的原因,我使用的配置是:firefox58.0.2,selenium3.11.0。

    那么接下来我们可以使用指令来输入一个网址试试。

    要输入网址,你必须知道接受你输入消息的对象是什么,例如这个网页,对象应该是这个文本框,而不是百度这个图标。那我们怎么获取呢?selenium提供了一系列的方法:find_element_by_xxx(这个xxx可以是name,id,class_name,xpath等等),通过这个方法得到的是一个指定网络元素的对象。那么知道了方法后要怎么传参呢?请按下f12,如图:

 

    点击左上角的那个图标,将鼠标移动到输入框的位置,这时候,工具栏会将输入框对应的代码在工具栏中显示出来:

 

    你可以看到,在这个属性栏中,有id字段,有class字段,有name字段,所以说这时候,如果你用如下代码:你都有可能获取到这个输入框。注意,为什么是可能?因为这个网页中,有可能不止一个id叫‘kw’的element,同理,其他也是。这时候find方法只会返回他找到的第一个element。

driver.find_element_by_id('kw')
driver.find_element_by_name('wd')
driver.find_element_by_class_name('s_ipt')

    那么唯一性如何确定呢?我目前知道两个方法:1.在工具栏搜一下,看看是不是还有其他同名的,如果没有,放心用。2.使用xpath,这往往是唯一的,但是也不是百分百能搜到,而且浏览器还要安装xpath的插件。怎么得到xpath呢?在这段蓝色背景的文字上右击->复制->xpath,就OK了:

driver.find_element_by_xpath('//*[@id="kw"]')

    那么这里就用xpath进行继续示范吧。这里插一句,如果需要批量的获取同类型的element,selenium提供了find_elements_by_xxx,其他跟上述一样,得到的是一个list。那么接下来我们在百度的输入框中输入一个微博的文本并点击回车: 

element = driver.find_element_by_xpath('//*[@id="kw"]')
element.send_keys(u'微博')

time.sleep(3)
element = driver.find_element_by_class_name('s_ipt').send_keys(Keys.ENTER)
    非常顺利的,与微博相关的网页被搜索出来。注意,这里的Keys里不仅包括了模拟回车的功能,感兴趣的可以多尝试下。

    GOOD,看来成功了。那么怎么点击进入到选中的网页中呢?用之前方法,选中网页中的第一个网站,考虑到网页的反应时间,建议在每次对浏览器进行操作的时候,加3秒的间隔。我们以第一个微博网站为例,使用click方法,实现模拟点击:

time.sleep(3)
element = driver.find_element_by_xpath('/html/body/div[1]/div[5]/div[1]/div[3]/div[1]/h3/a[1]')
element.click()

    这样,就可以计入到微博的主页啦。

   

    那么,怎么获取网页中的信息呢?我们假设获取百度搜索微博后网页中的标题内容。

time.sleep(3)
elements = driver.find_elements_by_class_name('t')
print(len(elements))

    此时,可以获取当前网页中载入的所有标题,个数为十个,如果需要看下标题的内容,可以如下操作:

time.sleep(3)
elements = driver.find_elements_by_class_name('t')
for element in elements:
    print(element.get_attribute('innerHTML'))

 这里再多说一句,element的属性除了‘innerHTML’外,还有很多,详情参考:‘https://www.cnblogs.com/shuai7729118/p/7777212.html’。

    这就是打印的结果:

C:\Python27\python.exe D:/Code/reptile/test.py

<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4C26DF6A',
'F3':'54E5243F',
'T':'1521448654',
'y':'FD567F9B'
 
,'rsv_gwlink':'1'
}" href="http://www.baidu.com/link?url=63_cG-kjuJu6Hmupdzih7a8p9Ujt8JtxOVIMNXv1pCq" target="_blank"><em>微博</em>-随时随地发现新鲜事</a><a href="http://trust.baidu.com/vstar/official/intro?type=gw" target="_blank" class="OP_LOG_LINK c-text c-text-public c-text-mult c-gap-icon-left">官网</a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'6E7FFEBB'
 
}" href="http://www.baidu.com/link?url=643H1xCCcVicdHXamoosh5jpE7IL3yeXA2n4JPvv_vUqZ_kXZ8oZU4UT7RXQU4zV" target="_blank">百度的<em>微博</em>_<em>微博</em></a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'FA759FFE'
 
}" href="http://www.baidu.com/link?url=AMkJRsmfGQ6bq_FhxevD-vHll5WRaogkSTbzFnz7EwS" target="_blank"><em>微博</em>搜索 - <em>微博</em></a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'BDEAEDA2'
 
}" href="http://www.baidu.com/link?url=Ax3sJRBOpm9sYrRIDUQJX_dtfYQ4v3n0nZb0RQtQaAsD_C80Koz21i1zTOx7agcW" target="_blank">郭德纲的<em>微博</em>_<em>微博</em></a>
<a class="favurl" style="background-image:url(https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=181218204,4281252600&amp;fm=58)" fav-url="http://t10.baidu.com/it/u=181218204,4281252600&amp;fm=58" data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DC6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'AAFB7799'
 
}" href="http://www.baidu.com/link?url=VTk1K7Xa9nD6Yjlw2rvf1NIbCWCxG_E5CbK0S7N8zyG" target="_blank">腾讯<em>微博</em>_你的心声,世界的回声</a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'BDDE5DFA'
 
}" href="http://www.baidu.com/link?url=zRxLEtfqrydoEd2BHt-jfhC6X5DjwuhCdy0tmpU9bxL7BWwdgg2Nyh08rxgGAzVlzAav_3PcRFjwDw955fgrtmPWNa2QEqm8dWKbt0XdQyG" target="_blank">周鸿祎的<em>微博</em>_<em>微博</em></a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DD6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'D7CFFEFC'
 
}" href="http://www.baidu.com/link?url=GrriIvfkOWb2fZIkNMZhhkGGfAuVaZ4VYn3GsQmrtWbJ7p31-JtRscrCWSLFiF_G" target="_blank">胡歌的<em>微博</em>_<em>微博</em></a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'FFFFFEFF'
 
}" href="http://www.baidu.com/link?url=9vwKQ7vDr7iDd6dl1RyjrgBw79rUYLSbyyOkfRKIeycUfxj37ghrrnXlI1xn4Zm-" target="_blank">文章同學的<em>微博</em>_<em>微博</em></a>
<a data-click="{
'F':'778317EA',
'F1':'9D73F1E4',
'F2':'4CA6DE6B',
'F3':'54E5243F',
'T':'1521448654',
'y':'FDDFBED7'
 
}" href="http://www.baidu.com/link?url=wDQ7dYf8PDPD6oEeCowTD43439QzvEPxmrj8dPiijelDOXslj5kzOuqjTxdMMf03" target="_blank">彭于晏的<em>微博</em>_<em>微博</em></a>


    <a href="http://www.baidu.com/link?url=0QJq4weJhrWe4yQVmoIOSdrmg2krtJl03oORhLlQiKOl5FJHl2mXAWPtI_stLP6WKuaWWt46x71rrO_QN6avh_" target="_blank"><em>微博</em>桌面最新官方版下载_百度软件中心</a>

    哇,看起来太乱了,那现在该怎么筛选呢?有两种方案,如果结构简单,格式统一的,我建议直接正则就ok了,如果复杂的,内容很多,不得不祭出beautifulsoup了,当然这个库就自己看下吧,这里就不再赘述了。    

    下面写个正则把人名啥的拉出来:

time.sleep(3)
elements = driver.find_elements_by_class_name('t')
for element in elements:
    print(re.findall('target="_blank">(.*)<em>(.*)</em>', element.get_attribute('innerHTML'))[0])
    这样就把所有的人名取出来来,当然编码是utf-8的,这里就懒得转了。

    (u'', u'\u5fae\u535a')
    (u'\u767e\u5ea6\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')
    (u'<em>\u5fae\u535a</em>\u641c\u7d22 - ', u'\u5fae\u535a')
    (u'\u90ed\u5fb7\u7eb2\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')
    (u'\u817e\u8baf', u'\u5fae\u535a')
    (u'\u5468\u9e3f\u794e\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')
    (u'\u80e1\u6b4c\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')
    (u'\u6587\u7ae0\u540c\u5b78\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')
    (u'\u5f6d\u4e8e\u664f\u7684<em>\u5fae\u535a</em>_', u'\u5fae\u535a')

    (u'', u'\u5fae\u535a')

    好啦,至此,基本的selenium用法就讲的差不多了,除了上述的方法外,selenium还有很多很实用的方法:

    比如最大化屏幕

driver.maximize_window()
    比如拉动滚动条至最底部
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")

    等等。

    只要你会python的基础语法,可以说,用selenium可以不用借助网络知识就可以实现一个简单的爬虫功能啦~但是,这是万不得已才使用办法,能用框架,当然用框架,切记!最后附上全部demo代码。

# !usr/bin/python
# -*- coding:utf-8 -*-

import re
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys


if __name__ == '__main__':
    driver = webdriver.Firefox()
    driver.get('https://www.baidu.com/')

    # driver.find_element_by_id('kw')
    # driver.find_element_by_name('wd')
    # driver.find_element_by_class_name('s_ipt')
    element = driver.find_element_by_xpath('//*[@id="kw"]')
    element.send_keys(u'微博')

    time.sleep(3)
    element = driver.find_element_by_class_name('s_ipt').send_keys(Keys.ENTER)

    # test for click
    # time.sleep(3)
    # element = driver.find_element_by_xpath('/html/body/div[1]/div[5]/div[1]/div[3]/div[1]/h3/a[1]')
    # element.click()

    time.sleep(3)
    elements = driver.find_elements_by_class_name('t')
    for element in elements:
        print(re.findall('target="_blank">(.*)<em>(.*)</em>', element.get_attribute('innerHTML'))[0])











猜你喜欢

转载自blog.csdn.net/BmwGaara/article/details/79611823