python抓取动态网页(数据怎么破()())

优采云 发布时间: 2021-10-09 15:02

  python抓取动态网页(数据怎么破()())

  介绍

  自从学了爬虫,每天不写个爬虫*敏*感*词*姐就觉得不爽:

  

  *敏*感*词*姐长得还不错,就是身体越来越瘦了,多喝点营养快递吧!

  

  (快来学Python爬虫,一起爬爬可爱的*敏*感*词*姐~)

  抓了太多,发现有些小网站很狡猾,开始反爬虫了。它们不直接生成数据,而是通过加载JS生成数据,然后你打开Chrome浏览器的开发者选项,然后你会发现Elements页面的结构和网络抓包返回的内容不一样. 网络抓包中没有对应的数据。数据应该放的地方竟然是JS代码,比如煎蛋的少女图:

  ">

  对于我这种不懂JS的安卓狗,不禁感叹:

  ">

  抓不到数据怎么破?一开始想自学一波JS基础语法。然后我去模拟抓包来获取别人的JS文件。JS竟然被加密了,要爬的页面太多了。什么时候分析每个这样的分析...

  ">

  我偶然发现有一个自动化测试框架:Selenium 可以帮助我们处理这个问题。简单说说这个东西的使用,我们可以写代码让浏览器:

  然后这个东西不支持浏览器功能。您需要在第三方浏览器中使用它。支持以下浏览器,需要将对应的浏览器驱动下载到Python对应的路径:

  Chrome: /a/chromium....FireFox: /mozilla/gec...PhantomJS: /IE: /index.htmlEdge: /en-us/micro...Opera: /operasoftwa...

  下面直接开始本节的内容吧~

  1.安装硒

  这个很简单,直接通过pip命令行安装:

  sudo pip install selenium

复制代码

  PS:我记得我公司小伙伴问我为什么在win上不能执行pip,我下载了很多pip。其实如果你安装Python3,它默认已经自带pip了。您需要配置额外的环境变量,pip。路径在Python安装目录的Scripts目录下~

  ">

  在Path后面加上这个路径就行了~

  ">2.下载浏览器驱动

  因为 Selenium 没有浏览器,所以需要依赖第三方浏览器。如果要调用第三方浏览器,需要下载浏览器的驱动。由于作者使用的是 Chrome,所以我们以 Chrome 为例。其他 浏览器自行搜索相关信息!打开 Chrome 浏览器并输入:

  chrome://version

复制代码

  可以查看Chrome浏览器版本的相关信息,这里主要注意版本号:

  ">

  61.好的,那么到下面网站查看对应的驱动版本号:

  /2.34/notes....

  ">

  好的,接下来下载v2.34版本的浏览器驱动:

  /index.html?...

  ">

  下载完成后,解压zip文件,将解压后的chromedriver.exe复制到Python Scripts目录下。(这里不用担心win32,64位浏览器可以正常使用!)

  PS:对于Mac,将解压后的文件拷贝到usr/local/bin目录下,再拷贝到usr/bin目录下。

  接下来我们写一个简单的代码来测试一下:

  from selenium import webdriver

browser = webdriver.Chrome() # 调用本地的Chrome浏览器

browser.get('http://www.baidu.com') # 请求页面,会打开一个浏览器窗口

html_text = browser.page_source # 获得页面代码

browser.quit() # 关闭浏览器

print(html_text)

复制代码

  执行这段代码会自动调出浏览器访问百度:

  ">

  并且控制台会输出HTML代码,也就是直接得到的Elements页面结构,JS执行后的页面~接下来就可以抓取我们的煎蛋少女图了~

  3.Selenium 简单实战:抢炒蛋妹图

  直接分析Elements页面的结构,找到你想要的关键节点:

  ">

  显然这是我们抓到的那个*敏*感*词*姐的照片。复制这个网址,看看我们打印出来的页面结构是否收录这个东西:

  ">

  是的这很好。有了这个页面数据,我们就来一波美汤获取我们想要的数据吧~

  ">

  经过上面的过滤,我们就可以得到我们妹图的URL:

  ">

  只需打开一个验证,啧:

  ">

  ">

  我看到下一页只有30个*敏*感*词*姐,这对我们来说显然不够。第一次加载的时候,我们得到一波页码,然后我们就知道有多少页了,然后我们去拼接URL加载差异。例如,这里总共有 448 页:

  ">

  只需将其拼接到此 URL 中:过滤以获取页码:

  ">

  ">

  接下来,我将填写代码,循环抓取每个页面上的*敏*感*词*姐,并将其下载到本地。完整代码如下:

  import os

from selenium import webdriver

from bs4 import BeautifulSoup

import urllib.request

import ssl

import urllib.error

base_url = 'http://jandan.net/ooxx'

pic_save_path = "output/Picture/JianDan/"

# 下载图片

def download_pic(url):

correct_url = url

if url.startswith('//'):

correct_url = url[2:]

if not url.startswith('http'):

correct_url = 'http://' + correct_url

print(correct_url)

headers = {

'Host': 'wx2.sinaimg.cn',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '

'Chrome/61.0.3163.100 Safari/537.36 '

}

try:

req = urllib.request.Request(correct_url, headers=headers)

resp = urllib.request.urlopen(req)

pic = resp.read()

pic_name = correct_url.split("/")[-1]

with open(pic_save_path + pic_name, "wb+") as f:

f.write(pic)

except (OSError, urllib.error.HTTPError, urllib.error.URLError, Exception) as reason:

print(str(reason))

# 打开浏览器模拟请求

def browser_get():

browser = webdriver.Chrome()

browser.get('http://jandan.net/ooxx')

html_text = browser.page_source

page_count = get_page_count(html_text)

# 循环拼接URL访问

for page in range(page_count, 0, -1):

page_url = base_url + '/' + str(page)

print('解析:' + page_url)

browser.get(page_url)

html = browser.page_source

get_meizi_url(html)

browser.quit()

# 获取总页码

def get_page_count(html):

soup = BeautifulSoup(html, 'html.parser')

page_count = soup.find('span', attrs={'class': 'current-comment-page'})

return int(page_count.get_text()[1:-1]) - 1

# 获取每个页面的*敏*感*词*姐

def get_meizi_url(html):

soup = BeautifulSoup(html, 'html.parser')

ol = soup.find('ol', attrs={'class': 'commentlist'})

href = ol.findAll('a', attrs={'class': 'view_img_link'})

for a in href:

download_pic(a['href'])

if __name__ == '__main__':

ssl._create_default_https_context = ssl._create_unverified_context

if not os.path.exists(pic_save_path):

os.makedirs(pic_save_path)

browser_get()

复制代码

  操作结果:

  ">

  看看我们的输出文件夹~

  ">

  是的,发了这么多*敏*感*词*姐,就是想骗你学Python!

  ">4.PhantomJS

  PhantomJS 没有界面浏览器。特点: 它将网站加载到内存中并在页面上执行JavaScript。因为它不显示图形界面,所以它比完整的浏览器运行效率更高。(如果某些Linux主机上没有图形界面,有界面的浏览器是不能使用的,可以使用PhantomJS来规避这个问题)。

  在 Win 上安装 PhantomJS:

  在 Ubuntu/MAC 上安装 PhantomJS:

  sudo apt-get install phantomjs

复制代码

  !!!关于 PhantomJS 的重要说明:

  今年 4 月,Phantom.js 的维护者宣布退出 PhantomJS,这意味着该项目可能不再维护!!!Chrome 和 FireFox 也开始提供 Headless 模式(不需要挂掉浏览器),所以估计使用 PhantomJS 的小伙伴会慢慢迁移到这两个浏览器。Windows Chrome 需要 60 以上的版本才能支持 Headless 模式。启用 Headless 模式也很简单:

  ">

  selenium 的官方文档中还写道:

  ">

  运行时也会报这个警告:

  ">5.Selenium实战:模拟登录CSDN并保存Cookie

  CSDN登录网站:/account/log...

  分析页面结构,不难发现对应的登录输入框和登录按钮:

  ">

  ">

  我们要做的就是在这两个节点输入账号密码,然后触发登录按钮,并将cookie保存到本地,然后就可以带着cookie访问相关页面了~

  首先写一个方法来模拟登录:

  ">

  找到你输入账号密码的节点,设置你的账号密码,然后找到登录按钮节点,点击它,然后等待登录成功。登录成功后,可以对比current_url是否发生了变化。然后保存Cookies,这里我使用的是pickle库,你可以使用其他的,比如json,或者字符串拼接,然后保存到本地。如果没有意外,应该可以拿到Cookie,然后使用Cookie访问主页。

  ">

  通过 add_cookies 方法设置 Cookie。参数是字典类型。另外一定要先访问get链接,再设置cookie,否则会报无法设置cookie的错误!

  通过查看右下角是否变为登录状态就可以知道是否使用Cookie登录成功:

  ">6.Selenium 常用函数

  Seleninum 作为自动化测试的工具,自然提供了很多自动化操作的功能。下面是我觉得比较常用的函数,更多的可以看官方文档:官方API文档:seleniumhq.github.io/selenium/do...

  1) 定位元素

  PS:将元素更改为元素将定位所有符合条件的元素并返回一个列表,例如:find_elements_by_class_name

  2) 鼠标操作

  有时需要在页面上模拟鼠标操作,如:单击、双击、右键、按住、拖动等,可以导入ActionChains类:mon.action_chains.ActionChains使用ActionChains(driver).XXX调用对应节点的行为

  3) 弹出窗口

  对应类:mon.alert.Alert,感觉用的不多...

  如果触发某个时间,弹出对话框,可以调用如下方法获取对话框:alert = driver.switch_to_alert(),然后调用如下方法即可:

  4)页面前进、后退、切换

  切换窗口:driver.switch_to.window("window name") 或者在driver.window_handles中遍历window_handles获取句柄:driver.switch_to_window(handle)driver.forward()# forward driver.back()#返回

  5) 页面截图

  driver.save_screenshot("Screenshot.png")

  6) 页面等待

  现在越来越多的网页使用 Ajax 技术,因此程序无法确定元素何时完全加载。如果实际页面等待时间过长,某个dom元素没有出来,而你的代码直接使用了这个WebElement,那么就会抛出NullPointer异常。

  为了避免元素定位困难,增加ElementNotVisibleException的概率。所以Selenium提供了两种等待方式,一种是隐式等待,一种是显式等待。

  显式等待:

  显式等待指定某个条件,然后设置最大等待时间。如果此时没有找到该元素,则会抛出异常。

  from selenium import webdriver

from selenium.webdriver.common.by import By

# WebDriverWait 库,负责循环等待

from selenium.webdriver.support.ui import WebDriverWait

# expected_conditions 类,负责条件出发

from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.PhantomJS()

driver.get("http://www.xxxxx.com/loading")

try:

# 每隔10秒查找页面元素 id="myDynamicElement",直到出现则返回

element = WebDriverWait(driver, 10).until(

EC.presence_of_element_located((By.ID, "myDynamicElement"))

)

finally:

driver.quit()

复制代码

  如果不写参数,程序会调用0.5s一次,检查元素是否默认已经生成。如果元素已经存在,它将立即返回。

  下面是一些内置的等待条件,你可以直接调用这些条件,而不用自己编写一些等待条件。

  title_istitle_containspresence_of_element_locatedvisibility_of_element_locatedvisibility_ofpresence_of_all_elements_locatedtext_to_be_present_in_elementtext_to_be_present_in_element_valueframe_to_be_available_and_switch_to_itinvisibility_of_element_locatedelement_to_be_clickable - 它显示和Enabled.staleness_ofelement_to_be_selectedelement_located_to_be_selectedelement_selection_state_to_beelement_located_selection_state_to_bealert_is_present

  隐式等待:

  隐式等待比较简单,就是简单的设置一个等待时间,以秒为单位。

  from selenium import webdriver

driver = webdriver.PhantomJS()

driver.implicitly_wait(10) # seconds

driver.get("http://www.xxxxx.com/loading")

myDynamicElement = driver.find_element_by_id("myDynamicElement")

复制代码

  当然,如果不设置,则默认等待时间为0。

  7.执行JS语句

  driver.execute_script(js语句)如滚动到底部:js = document.body.scrollTop=10000driver.execute_script(js)

  概括

  本节介绍一波使用 Selenium 自动化测试框架来捕获 JavaScript 动态生成的数据。Selenium 需要依赖第三方浏览器。注意 PhantomJS 无界面浏览器的过时问题。您可以使用 Chrome 和 FireFox 提供的 HeadLess 来替换它。; 通过抓取煎蛋女孩图片,模拟CSDN自动登录的例子,熟悉Selenium的基本使用,还是收获不少。当然,Selenium 的水还是很深的。目前我们可以用它来应对JS动态加载数据页面数据的抓取。

  最近有点冷,大家记得及时加衣服哦~另外,因为这周事情比较多,先把换的破了。下周见。下一个要啃的骨头是 Python 多线程。我可以在视觉上,恭敬地啃几节经文。敬请期待~

  ">

  顺便写下你的想法:

  下载本节源码:

  /coder-pig/R...

  本节参考资料:

  来吧,Py 交易

  想加群一起学Py可以加小猪智障机器人,验证信息收录:python,python,py,Py,加群,交易,混蛋之一关键词 可以通过;

  ">

  验证通过后回复群获取群链接(不要破机器人!!!)~~~欢迎像我这样的各类Py初学者和Py大神加入,一起交流学习♂ Xi, van ♂转向py。

  ">

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线