0x01 初步接触动态数据抓取
在开始学爬虫的时候会接触到一些使用普通的抓取方式获取不到的信息
例如我们想抓取到 白夜行 这本书的价格
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#coding:utf-8 import requests from lxml import etree import sys reload(sys) sys.setdefaultencoding( "utf-8" ) header={ 'Host': 'item.jd.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Accept-Encoding': 'gzip, deflate, br', } html=requests.get("https://item.jd.com/11153952.html",headers=header) selector=etree.HTML(html.text) #获取价格数据的xpath写法 price=selector.xpath('//strong[@id="jd-price"]/text()') print price |
运行后会发现抓取到的数据为空
1 2 |
[][Finished in 0.5s] |
查看源代码的时候会发现源代码中并不存在
所以可以得知我们需要抓取的数据是动态数据
0x02 selenium和phantomjs配合的简单用法
抓取动态数据的方法有多种,使用selenium模拟浏览器进行动态抓取是其中的一种方法,具体的安装与使用请看这里
===> selenium的安装以及使用
接下来是安装phantomjs,phantomjs下载地址 安装的教程也可以百度的到,就不贴出来了
因为使用selenuim进行模拟抓取的时候,会打开浏览器,显得很不方便,所以就使用phantomjs这个“无头浏览器”来模拟页面数据的抓取。
Phantomjs的相关介绍如下:
PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API。它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG。 PhantomJS 可以用于 页面自动化 , 网络监测 , 网页截屏 ,以及 无界面测试 等。
掌握了selenuim的基本用法之后,就可以开始写代码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#coding:utf-8 from selenium import webdriver import time import sys reload(sys) sys.setdefaultencoding( "utf-8" ) from selenium.webdriver.common.desired_capabilities import DesiredCapabilities dcap = dict(DesiredCapabilities.PHANTOMJS) dcap["phantomjs.page.settings.userAgent"] = ( "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0 " ) driver = webdriver.PhantomJS(desired_capabilities=dcap) driver.get("https://item.jd.com/11153952.html") time.sleep(2) #获取页面的价格数据 price=driver.find_element_by_xpath('//strong[@id="jd-price"]').text print price driver.close() |
哟呵,大功告成啦~
0x03 批量删除微博
值得一提的是,一开始我是用Phantomjs模拟登陆微博的时候发现使用
1 2 |
find_element_by_xpath("xxxx").click() |
使用xpath匹配的方法,有的时候会出现无法点击a标签或者是div标签的情况,为了避免这种情况发生可以通过css选择器选定id属性,然后执行点击动作。为了解决上面的问题,需要在python脚本里执行自己写入的js语句即可,给没有id的标签添加上id属性,通过css选择器选择即可点击。
代码如下
1 2 3 |
js = 'var box1=document.getElementsByClassName("cur W_fb")[0];box1.id="mybox";' driver.execute_script(js) #运行上面的js脚本 |
一切准备工作都做好了接下来可以开始写脚本运行啦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#coding:utf-8 from selenium import webdriver import time import sys reload(sys) sys.setdefaultencoding( "utf-8" ) from selenium.webdriver.common.desired_capabilities import DesiredCapabilities dcap = dict(DesiredCapabilities.PHANTOMJS) dcap["phantomjs.page.settings.userAgent"] = ( "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0 " ) driver = webdriver.PhantomJS(desired_capabilities=dcap) driver.get("http://weibo.com/") print '程序正在运行,请稍后'.decode('utf-8').encode('gbk') time.sleep(5) driver.maximize_window() time.sleep(3) #模拟登陆 try: print '正在登陆……'.decode('utf-8').encode('gbk') js = 'var box1=document.getElementsByClassName("cur W_fb")[0];box1.id="mybox";' driver.execute_script(js) logsub=driver.find_element_by_id('mybox').click() username=driver.find_element_by_xpath('//div[@class="info_list username"]/div/input').send_keys('你的用户名') password=driver.find_element_by_xpath('//div[@class="info_list password"]/div/input').send_keys('你的密码') sub=driver.find_element_by_xpath('//div[@class="info_list login_btn"]/a/span').click() print '登录成功'.decode('utf-8').encode('gbk') time.sleep(2) except: print '登录失败'.decode('utf-8').encode('gbk') driver.close() #模拟批量删除 try: weinote=driver.find_element_by_xpath('/html/body/div[1]/div/div[2]/div[3]/div[2]/div[2]/div[2]/div/div/div[2]/ul/li[3]/a/strong').click() global page page = 100 print '开始批量清除微博'.decode('utf-8').encode('gbk') except: print '批量删除微博失败'.decode('utf-8').encode('gbk') driver.close() def delweibo(): time.sleep(3) weicon=driver.find_elements_by_xpath('//div[@id="Pl_Official_MyProfileFeed__21"]/div/div[@class="WB_cardwrap WB_feed_type S_bg2 "]') count=0 manweibo=len(weicon) print '当前页面微博数量为:'.decode('utf-8').encode('gbk')+str(manweibo) if(manweibo==0): global page page=0 return page; for subweicon in weicon: count=count+1 sub1=subweicon.find_element_by_xpath('div/div/div/a').click() time.sleep(1) del1=subweicon.find_element_by_xpath('div/div/div/div[1]/ul/li[1]/a').click() yes1=subweicon.find_element_by_xpath('div/div/div/div[2]/div/p[2]/a[1]').click() print '已经删除一条微博'.decode('utf-8').encode('gbk') time.sleep(2) if(count==manweibo): print '下一页'.decode('utf-8').encode('gbk') return delweibo() def main(): delweibo() if __name__=="__main__": main() if(page==0): print '微博内容已经清空'.decode('utf-8').encode('gbk') time.sleep(1) driver.close() |
运行~大功告成,慢慢删吧~
代码写的很粗糙,欢迎表哥们的指点 ↖(^ω^)↗