大作业笔记--爬虫2|青训营笔记

182 阅读7分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

简介

在本次字节跳动第四届青训营中,我与我的队友选择了实现分布式爬虫的大作业,本文是我的第二篇针对该大作业的学习笔记。在上一篇的基础上,我了解了更多关于数据解析和浏览器自动化的知识。以下将针对这两个方面进行梳理总结。

目录

  1. 数据解析概述
  2. xpath解析
  3. selenium初步
  4. 总结

数据解析概述

对于爬虫,我们的需求往往不是总体地爬取一张页面的全部信息,而是重点关注其中的某个或某类信息,比如这张页面上有哪些图片,有哪些url链接可以让我们爬取到另外的页面等。而从整张页面中挑选出这样的信息就是数据解析。

通过查看页面的源码可以发现,解析的局部内容往往都会储存到标签之间或标签对应的属性中。如下图:

Screen Shot 2022-08-06 at 12.56.06.png

因此,可以得出,想要对这样的页面进行数据解析,简单来讲有两步:标签定位,和提取标签或其属性的内容。

而现有的知名度较高的数据解析方法有以下三种:

  1. 正则表达式
  2. bs4(beautiful soup)
  3. xpath

其中,正则表达式和xpath都较为通用,bs4只能用于python,而xpath又更为推荐,所以我在本文中主要整理xpath的常见用法。

xpath数据解析

我们首先要安装对应的python module,安装指令为:

pip/pip3 install lxml

关于xpath数据解析的使用,其流程可以大致分为两步:

  1. 实例化一个etree对象,加载被解析页面
  2. 调用etree对象中的xpath方法,结合xpath表达式,实现标签的定位和内容的捕获

下面联系具体代码整理其具体流程

实例化etree对象

关于这一步,十分简单,但是注意xpath可以支持两类情况,第一类情况是用户本地已经存有一个html文档,现在希望针对这个本地的文档解析,将其源码数据加载到etree对象中,代码为:

etree对象名=etree.parse(FilePath)

第二类便是将从互联网上获取的源码数据加载到etree对象中,代码为:

etree对象名=etree.HTML(page_text)

调用xpath方法进行标签定位和内容捕获

调用etree对象中的xpath方法通用的代码格式为:

x=etree对象名.xpath(xpath表达式)

其返回一个element对象,我们在这里用x接收。

具体xpath中,主用/符号进行标签层级的分割,单个/表示从根节点开始定位,一个/表示一个层级。比如一般根节点的标签都是<html>,这个层级往下可能会有<head>,<head>下可能有<title>,如果现在我们希望定位到<title>,捕获其中的内容,那么代码可以写为:

tree.etree.parse(FilePath)
t=tree.xpath('/html/head/title')

但如上文所提,这里得到的是一个element对象,但我们想要的可能就是这个title具体的字符串,那么可以在xpath表达时候加上/text():

t=tree.path('/html/head/title/text()')

这是单个/的用法。//则表示多个层级,比如我们想从html定位到div标签,但是不知道或不想罗列其中的标签,那么可以写为:

x=tree.xpath('html//div')

如果左侧什么都不写,就表示从任意位置定位到这个标签,如:

x=tree.xpath('//div')

除了定位标签,获取标签中的内容,我们上文还提到xpath表达式可以定位一个标签的属性,该功能通过[@属性=我们想要找的内容]来实现,比如,假设div这个标签有一个属性叫class,而这个属性中名为‘xxx’下的有标签p是我们想得到的,那么代码可以编写为:

x=tree.xpath('//div[@class='xxx']/p')

类似于上文或许文本,有时候我们想得到的是属性内容本身,那么代码可以编写为:

x=tree.xpath('//定位标签/@属性名')

最后,xpath还支持同时使用多个xpath表达式,来表示符合多个情况的内容都可以获取,这样的情况下将两个表达式用“或”符号,即|来分隔开即可。

selenium初步

在上一篇爬虫学习笔记中,提到有时候我们想从页面中得到的数据是动态加载出来的,这个时候我们原来的解决办法是人工查看对应的阿贾克斯请求是什么,然后传入参数,得到这些数据,这个过程是比较麻烦的。selenium就是一个可以便捷获取网页中动态加载的数据,实现模拟登陆等的基于浏览器自动化的模块。在这部分对其做简单整理。

安装selenium

安装selenium的指令:

pip/pip3 install selenium

下载浏览器的驱动程序

要用selenium访问浏览器,我们需要先下载对应自己电脑用的浏览器版本的浏览器驱动程序,一般官方会提供,比如google chrome在此提供:chromedriver.storage.googleapis.com/index.html

下载,保存即可,记住保存路径,为方便期间可以和爬虫程序存放在同一个文件夹里。

实例化一个浏览器对象

下一步便是通过selenium实例化一个浏览器对象,代码实现为:

from selenium import webdriver
bro=webdriver.对应的浏览器名比如Chrome.(executable_path='之前浏览器驱动器的下载地址,比如在同一个文件夹的话就是./chromedriver')

编写操作代码

做了以上的准备工作,下一步就是获取,解析我们想要的网页的内容,selenium的特殊之处就在于有一些我们想要解析的数据是动态加载的,直接用requests得到的page source中并不包括,但是selenium可以得到,让我们轻松通过xpath等方式解析这个动态加载出来的数据。

代码实现为:

bro.get(url)
page_text=bro.page_source
tree=etree.HTML(page_text)
...用xpath正常解析数据

具体selenium可以实现的操作,除了简单得到页面数据以外还有很多,比如进行交互,找到搜索框搜索特定内容等,在此不一一罗列。下面再整理两个比较常见的操作。

无头浏览器

正常来讲,在跑如上selenium的代码时,我们是会看到浏览器的窗口弹出来,特定网页被打开的这个具体的过程的,但有时候在运行爬虫时,我们不需要也不想要这个浏览器网页真实地弹出来,这就是无头浏览器的概念。为实现这一点,我们需要从selenium中再倒入一个option,并将其作为参数传到我们获取网页的过程中:

from selenium.webdriver.chrome.options import Options
bro=webdriver.Chrome(executable_path='./chromedriver',chrome_options=chrome_options)

规避被检测

就像上一篇笔记中提到的UA检测,使用selenium同样会有被反爬虫机制检测的问题,应对这一点,我们需要倒入ChromeOption然后再或许网页内容的时候传入一个option参数,来进行伪装:

from selenium..webdriver import ChromeOptions
option=ChromeOption()
bro=webdriver.Chrome(executable_path='./chromedriver',chrome_options=chrome_options,options=option)

总结

我在现阶段关于爬虫学习最大的感悟就是对于selenium模块的好奇,在初步的应用中,已经可以看出其强大,希望可以进行更深入的了解,使自己对爬虫的使用基础更为巩固。关于数据解析,这是一个很大的课题,要如何让数据解析变得更高效,关键,如何将其融入分布式的框架中,是完成青训营大作业必须需要考虑的。