目录
- 爬虫-ajax数据爬取
- 1. ajax数据
- 2. selenium+chromedriver知识准备
- 3. selenium+chromedriver实战拉勾网爬虫代码
爬虫-ajax数据爬取
1. ajax数据
ajax (异步JavaScript 和 XML)(读作阿贾克斯),ajax可以时网页实现异步更新,一般使用的json数据交互,即在不重新加载整个页面也可以对网页的部分进行更新,ajax技术加载的数据在网页源代码中是看不到的,只能看到url加载的html部分
获取ajax数据的两种方式
1 分析ajax调用的接口,发现url的参数,再通过代码请求这个接口,直接拿到json数据,有时json数据可能是加密的,或者发送post请求获取json数据并且表单中的数据是按照一定规则写的,这时需要分析js代码,就很麻烦了。
2 Selenium+chromedriver 获取动态数据,Selenium 相当于可以模拟输入、删除和点击操作以及cookie chromedriver是一个驱动chrome浏览器的驱动程序,使用它可以驱动浏览器。这种方式可以直接获取网页中全部的代码,包括ajax技术加载的数据。例如有的网站点击“更多”按钮后可以加载的数据,将全部被获取。虽然这种方式简单粗暴,但每次请求页面时都会打开一个页面,加载数据和渲染页面,显得过于笨重。
2. selenium+chromedriver知识准备
chromedriver是谷歌浏览器的驱动程序,使用selenium可以操作它
chromedriver.exe需要放在一个非中文目录下
2.1 selenium+chromedriver简单操作
form selenium import webdriverdriver_path = r‘D:\chromedriver\chromedriver.exe‘ ?# 指明路径driver = webdriver.Chrome(executable_path=driver_path) ?# 创建driver实例,将路径传入driver.get("https://www.baidu.com") ?# get方式打开百度,注意一定要加https:// 否则会报错driver.page_source # 获取源代码,然后可以扔给正则表达式或者xpath解析,这里可以直接获取ajax数据driver.close() #关闭一个页面driver.quit() #关闭整个浏览器
2.2 常用表单元素
input type=‘text/password/email/number‘ 文本框
button input [type=‘submit‘] 按钮 例如登陆
checkbox input type=‘checkbox‘ 例如记住密码选项
select 下拉菜单
2.3 模拟点击
driver.get(‘https://www.douban.com/‘)remenberBtn = driver.find_element_by_id(‘form_remember‘)remenberBtn.click()
2.4 行为链
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains ?#导入driver和行为链类driver_path = r‘D:\chromedriver\chromedriver.exe‘ ??#指定路径driver = webdriver.Chrome(executable_path=driver_path) ?#创建对象driver.get(‘https://www.qq.com/‘) ??#打开网页moveTag = driver.find_element_by_xpath("//div[@class=‘more-txt‘]") #定位腾讯网中“更多”按钮clickTag = driver.find_element_by_xpath("//ul[@class=‘sub-list cf‘]/li[1]") ?#定位“独家”按钮actions =ActionChains(driver) ??# 创建行为链对象actions.move_to_element(moveTag) ??# 移动到定位点actions.click(moveTag) ?# 点击 ??好像不点击也可以actions.move_to_element(clickTag) ?# 移动到”独家“按钮actions.click(clickTag) # 点击actions.perform() ?# 必须调用的函数 ??否则不会执行之前定义好的行为# drver.find_element_by_xpath("") 意味着可以使用xpath语法找到想要点击的按钮或输入框# 类似的还有id ?class ?css
2.5 页面等待
1 隐式等待driver.implicitly_wait(x) ?# x是等待时间 ??x秒
2 显示等待from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver_path = r‘D:\chromedriver\chromedriver.exe‘driver = webdriver.Chrome(executable_path=driver_path)driver.get(‘https://new.qq.com/ch/ori/‘)try: ???WebDriverWait(driver, 10).until( ????????????????# 这里使用WebDriverWait类填入参数 ??10代表等待10s未出现则抛出异常 ???EC.presence_of_element_located((By.CLASS_NAME, ‘s ‘)) ????????#这里就是等待条件 即当class属性=s 被加载后条件达成)finally: ???print("2222") ??# 这样的话当没有等待到期望的条件就可以做其他事情
2.6 窗口
打开多个窗口driver.get(‘https://new.qq.com/ch/ori/‘)driver.execute_script("window.open(‘https://www.douban.com/‘)") #使用JavaScript脚本打开新页面
driver.get(‘https://new.qq.com/ch/ori/‘)driver.execute_script("window.open(‘https://www.douban.com/‘)") ??# 打开两个页面print(driver.current_url) ??# 打印当前urldriver.switch_to.window(driver.window_handles[1]) # ?切换窗口 ??窗口列表中第二个窗口的索引是1print(driver.current_url) ?# 打印当前url
2.7 代理ip
driver_path = r‘D:\chromedriver\chromedriver.exe‘options = webdriver.ChromeOptions() ?# 创建配置对象options.add_argument("--proxy-server=http://221.6.32.206:41816") ?# 写入配置driver = webdriver.Chrome(executable_path=driver_path, options=options) ?# 写入参数driver.get(‘https://www.baidu.com/s?wd=ip‘)
3. selenium+chromedriver实战拉勾网爬虫代码
# 拉勾网的反爬太恶心了,于是用selenium+chromedriver来爬,结果还是被封了,我去import reimport timefrom selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Byfrom lxml import etreeclass LagouSpider(object): ???def __init__(self): ???????driver_path = r‘D:\chromedriver\chromedriver.exe‘ ?# 指定chromedriver 的路径 ???????self.driver = webdriver.Chrome(executable_path=driver_path) ???????self.base_url = ‘https://www.lagou.com/jobs/list_python?px=default&city=%E6%88%90%E9%83%BD#filterBox‘ ??# 拉勾网搜索python的页面url ???????self.data = [] ?# 用来存放字典 ???def get_url_list(self): ???????while True: ???????????self.driver.get(self.base_url) ?# 访问拉勾网 ???????????# 获取页面全部文本信息,这里可以直接获取ajax技术返回的数据, ???????????# 如果用requests库需要找到发送json请求的数据包 ???????????text = self.driver.page_source ???????????try: ???????????????# 等待职位信息的url出现,timeout=3s ???????????????WebDriverWait(self.driver, 3).until( ???????????????????EC.presence_of_element_located((By.CLASS_NAME, ‘position_link‘)) ???????????????) ???????????????# 获取url并调用get_info函数 ???????????????url_list = re.findall(r‘<a class="position_link" href="(.*?)" target=.*?>‘, text, re.S) ???????????????for i in url_list: ???????????????????self.get_info(i) ???????????finally: ???????????????# 判断是否已到最后一页 ???????????????if len(re.findall(r‘class="pager_next pager_next_disabled"‘, text, re.S)) != 0: ???????????????????self.driver.quit() ???????????????????break ???????????????# 找到下一页的位置并点击 ???????????????else: ???????????????????nextPageTag = self.driver.find_element_by_xpath("//div[@class=‘pager_container‘]/span[last()]") ???????????????????nextPageTag.click() ???def get_info(self, url): ???????# 打开新窗口,移动driver,不移动无法获取page_source ???????self.driver.execute_script("window.open(‘{}‘)".format(url)) ???????self.driver.switch_to.window(self.driver.window_handles[1]) ???????try: ???????????# 提取信息,因为职位描述信息的标签实在是太乱了,还是用xpath舒服一点 ???????????html = etree.HTML(self.driver.page_source) ???????????work_name = re.findall(r‘<div class="job-name" title="(.*?)">‘, self.driver.page_source, re.S)[0] ???????????????????????salary = re.findall(r‘<span class="salary">(.*?)</span>‘, self.driver.page_source, re.S)[0] ???????????# 获取职位描述信息 ???????????temp = html.xpath("//dd[@class=‘job_bt‘]//div/p/text()") ???????????describe = ‘‘ ???????????for i in temp: ???????????????describe += i ???????????describe = re.subn(r‘\s*‘, ‘‘, describe) ???????????temp = { ???????????????‘job_name‘: work_name, ???????????????‘describe‘: describe[0], ???????????????‘salary‘: salary ???????????} ???????????print(temp) ???????????# 放入列表中,方便写入csv或者txt ???????????self.data.append(temp) ???????except: ???????????# 出错的页面打印出来 ???????????print(url) ???????????time.sleep(5) ???????finally: ???????????# 关闭页面,移动driver到最开始的base_url ???????????self.driver.close() ???????????self.driver.switch_to.window(self.driver.window_handles[0]) ???????????time.sleep(1) ???def run(self): ???????self.get_url_list()if __name__ == ‘__main__‘: ???spider = LagouSpider() ???spider.run()
爬虫1.5-ajax数据爬取
原文地址:https://www.cnblogs.com/bitterzZ/p/10195107.html