Arya

爬虫初探(五)——关于selenuim的一些七七八八的容易忽略的关键点
0x01这个真的是呕心沥血 花了很久的时间来研究,真的超级心塞。由于这些误区直接导致我浪费了很久时间来研究自己到...
扫描右侧二维码阅读全文
05
2017/04

爬虫初探(五)——关于selenuim的一些七七八八的容易忽略的关键点

0x01

这个真的是呕心沥血
QQ鍥剧墖20170405134407.jpg
花了很久的时间来研究,真的超级心塞。由于这些误区直接导致我浪费了很久时间来研究自己到底是哪个地方出现了问题,好在最后在各位师傅们的帮助下,虽然摔得头破血流也算是没有白白浪费。

0x02 关于防爬

关于time模块的一些碎碎念

在模拟抓取新浪微博的用户头像url时,我一开始的代码是这个样子的

#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
from selenium import webdriver

url="http://weibo.com/u/2138925605?refer_flag=1087030701_2975_2002_0&is_hot=1"
driver=webdriver.Chrome()
driver.get(url)
url=driver.find_element_by_xpath("//p[@class='photo_wrap']/img").get_attribute('src')
print url
driver.close()

然后
给我预料之外的来了个我当时都没有反应过来的报错
Traceback (most recent call last): File "G:\pycharm\vuLogin\weibourl.py", line 16, in url=driver.find_element_by_xpath("//p[@class='photo_wrap']/img").get_attribute('src') File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 295, in find_element_by_xpath return self.find_element(by=By.XPATH, value=xpath) File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 754, in find_element 'value': value})['value'] File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 238, in execute self.error_handler.check_response(response) File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 193, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//p[@class='photo_wrap']/img"} (Session info: chrome=56.0.2924.87) (Driver info: chromedriver=2.28.455520 (cc17746adff54984afff480136733114c6b3704b),platform=Windows NT 10.0.14393 x86_64)
其实也没什么好看的,重点的地方就在倒数第三行的这里selenium.common.exceptions.NoSuchElementException: Message: no such element:
简单粗暴的翻译就是,你要找的这个元素我找不到 ╮( ̄▽ ̄)╭
我当时是在怀疑人生的,毕竟网页也打开了,什么都搞定了,怎么会这样??
QQ鍥剧墖20170405140113.jpg
好吧,调试bug开始

遇到这样的问题,一般就从报错语句的上方开始排查问题,既然问题出现在url=driver.find_element_by_xpath("//p[@class='photo_wrap']/img").get_attribute('src')之前,但是页面又的确可以打开,也证明了driver.get(url)以及以上的语句都是可以正确运行的,唯一的办法就是查找源码的问题,看看是不是源码出错。
print driver.page_source
打印出抓取的源码
看到源码的时候我的内心是崩溃的
fuvk.jpg
抓取到的是微博开启了防爬机制后的源码,完全找不到任何和当前页面有关的代码啊!(╯‵□′)╯︵┴─┴
然后开始了漫长而又徒劳的百度,实际上百度并没有告诉我要怎么办,我委屈的去找了xrmht表哥,表哥很暖心的帮我跑了一遍代码,然后告诉我,我的代码和他一些别的爬虫代码不一样的地方在,我的代码里没有使用time.sleep()这个推迟调线程的时间函数,让我去修改一下看看。
真的是听君一句话,胜过半天的百度。
dalao.jpg
果然抓到了我需要的用户头像的url
后来的代码是这样子的

#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
from selenium import webdriver
import time

url="http://weibo.com/u/2138925605?refer_flag=1087030701_2975_2002_0&is_hot=1"
driver=webdriver.Chrome()
driver.get(url)
# print driver.page_source
time.sleep(5)
url=driver.find_element_by_xpath("//p[@class='photo_wrap']/img").get_attribute('src')
print url
driver.close()

成功的抓取到了url!!
http://tva1.sinaimg.cn/crop.16.0.412.412.180/7f7d6a25gw1eoesw1hax6j20c80bjdhq.jpg
因为有的网站存在防爬机制,只需要加上time.sleep()函数即可

0x03 关于登录前的一些步骤

抓取是抓取结束了啊,但是我还是要模拟登陆啊,我以为解决了time的问题就万事大吉了,果然我太天真了 QAQ
代码呈上

#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
from selenium import webdriver
import time

url="https://passport.jd.com/new/login.aspx"
driver=webdriver.Chrome()
driver.get(url)
time.sleep(5)
username=driver.find_element_by_xpath('//input[@id="loginname"]').send_keys('用户名')
password=driver.find_element_by_xpath('//input[@id="nloginpwd"]').send_keys("密码")
submit=driver.find_element_by_xpath('//a[@id="loginsubmit"]').click()

然后报错
Traceback (most recent call last): File "G:\pycharm\vuLogin\loginJD.py", line 17, in username=driver.find_element_by_xpath('//input[@id="loginname"]').send_keys('用户名') File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 347, in send_keys self._execute(Command.SEND_KEYS_TO_ELEMENT, {'value': keys_to_typing(value)}) File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 491, in _execute return self._parent.execute(command, params) File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 238, in execute self.error_handler.check_response(response) File "E:\Sakura\python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 193, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.ElementNotVisibleException: Message: element not visible (Session info: chrome=56.0.2924.87) (Driver info: chromedriver=2.28.455520 (cc17746adff54984afff480136733114c6b3704b),platform=Windows NT 10.0.14393 x86_64)
重点报错语句:
selenium.common.exceptions.ElementNotVisibleException: Message: element not visible
大致的意思就是loginname这个元素不可见
于是我一脸懵逼的抓下了源代码,结果在源代码里找到了id="loginname"这个input输入框
我的内心是崩溃的,明明源代码已经读取到了怎么会不可见?????
zys.jpg
无奈之下直接粘贴百度来的模拟登陆代码,根本不行,毕竟网页更新是正常的,之前的代码一定是不可以用了,然后我怀疑了一晚上的人生,拉着学长跑去吃了一顿饭,思考了半天依旧没有任何思路,觉得这一定是人品问题了。
苦.jpg
第二天,跑到了一些群里问也没有回复,突然想起来认识一个写爬虫的表姐,委屈巴巴的问了这个问题,小姐姐让我发了一下链接,然后一语道破:
https://passport.jd.com/new/login.aspx
这个页面打开之后是下面这个样子
jddlg.png
如果需要使用账号密码登录,需要点击账户登录,如果不点击的话,是没有办法获取到那个文本框的,所以上面的报错是元素不可见,而不是不存在。
个人的理解就是因为是模拟浏览器登录,所以每一步都要为它做好,包括点击账号密码登录框
于是修改了代码,果然可以了~

#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
from selenium import webdriver
import time

url="https://passport.jd.com/new/login.aspx"
driver=webdriver.Chrome()
driver.get(url)
time.sleep(5)
numsud=driver.find_element_by_xpath('//div[@class="login-tab login-tab-r"]/a').click()
# print driver.page_source
username=driver.find_element_by_xpath('//input[@id="loginname"]').send_keys('用户名')
password=driver.find_element_by_xpath('//input[@id="nloginpwd"]').send_keys("密码")
submit=driver.find_element_by_xpath('//a[@id="loginsubmit"]').click()

噢耶~ (〃ω〃)

0x03

登录好了之后真的是开心得不得了,浪里个浪
QQ鍥剧墖20170405163445.gif
然后打算来抓一抓京东的别的价格,于是就有了新的一轮折腾,至此也感觉算是稍微了解了selenuim模拟浏览器的真正意思
url:https://shouji.jd.com/
起源是我的手机屏幕被我一不小心摔碎了,真的感觉严重影响我看动漫的质量,随手翻了一下京东,想看看手机都是什么价格,反正买不起
QQ鍥剧墖20170322212526.gif
看了一下高性价比这一栏,准备抓一下优品推荐里的手机价格~
然后写代码

#coding:utf-8
import time
url="http://shouji.jd.com/"
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(url)
time.sleep(5)
# money=driver.find_elements_by_xpath('//ul[@class="today-list clearfix selected"]/li/div[3]')
money=driver.find_elements_by_xpath('//ul[@class="tab-cont curr"]/li/div[2]')
for eachmoney in money:
    print eachmoney.text
driver.close()

结果就是不报错,只能抓到一片空格,还带换行的 QWQ
果然python不会这么轻易放过我,永远都数不尽的bug 〒▽〒
然鹅我也的确习惯了
之后尝试了点击优品推荐这个标签也不行
真的是心灰意冷到怀疑人生
QQ鍥剧墖20170405165238[1].jpg
外面还在下雨,晚饭还没吃,当时真的蛮想放弃的,然后在也不知道第多少次尝试的时候,在模拟浏览器打开后顺手来了最大化,然后滑到了那个页面,结果!!!结果!!!价格抓下来了!!!
狂喜!!!
真的是感觉一道阳光照进了生命!
当时就突然反应过来了,因为在程序自动打开浏览器的时候,这些元素在当前情况下是看不见的,需要下滑鼠标才可以,而且还需要暂停在该界面1-2s确保页面读取完毕
代码如下:

#coding:utf-8
import time
url="http://shouji.jd.com/"
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get(url)
time.sleep(5)
# money=driver.find_elements_by_xpath('//ul[@class="today-list clearfix selected"]/li/div[3]')
# driver.maximize_window() //界面最大化,可以省去;
youpin=driver.find_element_by_xpath('/html/body/div[11]/div/div/div[2]/div[2]/ul[1]')//优品标签位置
ActionChains(driver).move_to_element(youpin).perform()//滑动鼠标,为了显示需要抓取的价格页面
time.sleep(2)//读取页面
money=driver.find_elements_by_xpath('//ul[@class="tab-cont curr"]/li/div[2]')
for eachmoney in money:
    print eachmoney.text
driver.close()

最后成功抓到价格
¥1499.00 ¥1549.00 ¥2299.00 ¥2899.00 ¥2299.00 ¥949.00 ¥2699.00 ¥2798.00
从这个时候开始我就不太喜欢selenium了,相当于是自己操作浏览器,抓取动态元素的时候也就需要考虑到页面的最大化,将鼠标滑动到元素直至可见,以及各种页面问题
一点点的没考虑到有可能爆出各种bug

还是尝试一下不要打开浏览器的方式比较好
( ・ˍ・)
果然还是要去学scrapy-splash和Phantomjs

Last modification:January 23rd, 2019 at 10:54 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment