写点什么

一入爬虫深似海,从此早睡是路人

用户头像
Thrash
关注
发布于: 2021 年 04 月 22 日
一入爬虫深似海,从此早睡是路人

“网络爬虫”又称“网络蜘蛛”,是一种在互联网上自动采集数据的自动化程序。爬虫的规模可大可小,大到百度、谷歌搜索,小到文本采集、自动采集图片等。


1 获取目标地址


下面介绍如何获取准备爬取内容的 URL。以阿里云漏洞预警页面为例,我们要得到的是漏洞预警标题、同标题 URL、漏洞预警公告时间等信息。图 1 中 URL 就是我们准备爬取的地址:


可获取目标的 Python 爬虫代码片段如下:


#获取目标 urls = ['https://help.xxxxxx.com/n***/92****/{}.html'.format(str(i)) for i in range(0,2,1)]for url in urls:html = get_html(url)其爬取结果如图 2 所示:


爬虫的本质是网络请求,在请求一个网页获得响应后获取 html 源码,接着处理获取到的 html 源码,并提取想要的数据,如图 3 所示。


出于降低编程难度以及代码重用等方面的考虑,通常将每个功能封装为一个个函数。


2 获取当前 URL 的 HTML


图 4 就是我们需要的 HTML 内容,我们将通过 python 的 requests 库对其进行获取。


通过 requests 库获取目标页面的 HTML 源码如下所示。考虑到代码比较容易理解,所以不在此处做过多说明。import requestsdef get_html(url):'''获得 HTML'''headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/53


7.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'}response = requests.get(url, headers=headers)if response.status_code == 200:response.encoding = 'utf-8'return response.textelse:return


从上述的源码可以看出,我们可通过 requests 库的 get 函数直接获取到目标页面的 HTML 源码。


requests 库的的其他常用方法如图 5 所示。


另外,在使用 requests 库时,我们还可以添加一些字段,如表 1 所示。


表 1params 字典或字节序列,作为参数增加到 url 中 data 字典、字节序列或文件对象,作为 Request 的内容 json JSON 格式的数据,作为 Request 的内容 headers 字典,HTTP 定制头 cookies 字典或 CookieJar,Request 中的 auth : 元组支持 HTTP 认证功能 files 字典类型,传输文件 timeout 设定超时时间,秒为单位 proxies 字典类型,设定访问代理服务器,可以增加登录认证 allow_redirects True/False,默认为 True,重定向开关 stream True/False,默认为 True,获取内容立即下载开关 verify True/False,默认为 True,认证 SSL 证书开关 cert 本地 SSL 证书 auth 元组,支持 HTTP 认证功能


使用参数 cookies、proxite 与 verify 的代码示例如下:


• 小例子• cookies = {'cookies_are':'working'}• proxite = {• 'http':'http://127.0.0.1:8080',• 'https':'https://127.0.0.1:8080'• }• res = requests.get(url, cookies=cookies, proxite=proxite, verify=False• )#verify=False 在请求的时候把 verify 参数设置为 False 就可以关闭证书验证了


另外在 header 内添加些其他能用到的字段,可以达到自己编辑 http 响应头的目的,代码片段如下。


headers = {'Proxy-Connection': 'keep-alive','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9'}不同页面 HTML 的获取条件是不一样的。对此,我们在使用的时候需要根据实际情况进行编写,一般情况下添加 UA 即可。如果我们的目标是一个网站登录后的页面,为了能爬取到 HTML,我们还需要用到 cookie 字段,如图 6 所示,或者表单模拟用户登录。


#表单模拟用户登录 import requestsfrom fake_useragent import UserAgent#生成随机 UAurl = 'https://*****.com/login'headers = {'User-agent' : UserAgent().random,}data = {'name' : '你的','password' : '你的'}response = requests.post(url,headers=headers,data=data)response.encoding = 'utf-8'print(response.text)


其他字段对于一般爬虫而言不一定有用,但笔者也将它们列举出来,希望可以为读者拓宽思路。


3 数据提取


XPathXPath 即 XML 路径语言(XML Path Language),它是一种用来确定 xml 文档中某部分位置的语言。


xml 文档(html 属于 xml)是由一系列节点构成的树,例如:


<html><body><div ><p>Hello world<p><a href="/home">Click here</a></div></body></html>


xml 文档的节点有多种类型,其中最常用的有以下几种:• 根节点整个文档树的根。• 元素节点 html、body、div、p、a。• 属性节点 href。• 文本节点 Hello world、Click here。


节点间的关系有以下几种:• 父子 body 是 html 的子节点,p 和 a 是 div 的子节点。反过来,div 是 p 和 a 的父节点。• 兄弟 p 和 a 为兄弟节点。• 祖先/后裔 body、div、p、a 都是 html 的后裔节点;反过来 html 是 body、div、p、a 的祖先节点。


XPath 常用的基本语法如图 7 所示。


下面,我们看看 XPath 的 3 个常用函数的使用。String(arg):返回参数的字符串 Contains(str1,str2):判断 str1 中是否包含 str2,返回布尔值 Text():提取文本


举下面这个例子说明:<div class="c-span9 c-span-last"><div><span class=" newTimeFactor_before_abs c-color-gray2 m">2020 年 6 月 19 日 </span></div><style>.user-avatar {}</style><div class="f13 c-gap-top-xsmall se_st_footer user-avatar"><a target="blank" href="http://www.baidu.com/;" style="text-decoration:none;position:relative;"><div class="c-img c-img-circle c-gap-right-xsmall" style="display: inline-block;width: 16px;height: 16px;position: relative;top: 3px;vertical-align:top;"><img src=""></div>知乎</a><div class="c-tools c-gap-left" id="tools_4828209406812473379_2" data-tools="{"title":"通俗的讲,网络爬虫到底是什么? - 知乎","url":"http://www.baidu.com/link?url=7rZRcme-wDX4h3VV5_YIsgYiQ9k-Vno9y5n5VMA9uSZT9_bMdDBN9RdvSMVyQsPWu91QvJbSz5Zsa6mngIvqj"}"><i class="c-icon f13"></i></div><span><span></span></span><style>.snapshoot, .snapshoot:visited {color: #9195A3!important;}.snapshoot:active, .snapshoot:hover {color: #626675!important;}</style><a data-click="{'rsv_snapshot':'1'}" href="http://cache.baiducontent.com" target="_blank" class="m c-gap-left c-color-gray kuaizhao snapshoot">百度快照</a></div></div>例如这个 html 代码,假设我需要提取的是百度快照四个字。就可以构造如下的 XPath。


//div[@class="c-row c-gap-top-small"]/div/div/a[2]


可以看到效果如图 8 所示。


CSS 选择器


CSS 选择器的语法比 XPath 更简单一些,但功能不如 XPath 强大。实际上,当我们调用 Selector 对象的 CSS 方法时,在其内部会使用 Python 库 cssselect 将 CSS 选择器表达式翻译成 XPath 表达式,然后调用 Selector 对象的 XPATH 方法。CSS 选择器的常用的基本语法如图 9 所示。


CSS 选择器的例程如下所示。print(soup.select('a[href="http://example.com/elsie"]')) # 寻找 a 标签中 href="http://example.com/elsie"的标签 print(soup.select('a[href^="http://example.com/"]')) # 寻找 href 属性值是以"http://example.com/"开头的 a 标签 print(soup.select('a[href$="tillie"]'))#寻找 href 属性值是以 tillie 为结尾的 a 标签 print(soup.select('a[href*=".com/el"]'))#寻找 href 属性值中存在字符串”.com/el”的标签 a


正则数据提取正则表达式是一种文本模式,包括普通字符和特殊字符。正则表达式使用单个字符串来描述、匹配一系列某个句法规则的字符串。


虽然繁琐,但正则表达式同时也是强大的,学会应用之后可以提高效率。许多程序设计语言都支持利用正则表达式进行字符串操作。


常用的正则表达式如表 2 所示。表 2 用户名 /^[a-z0-9_-]{3,16}/十六进制值 /^#?([a-f0-9]{6}|[a-f0-9]{3})//^[a-z\d]+(.[a-z\d]+)@(\da-z?)+(.{1,2}[a-z]+)+$/URL /^(https?://)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?/HTML 标签 /^<([a-z]+)([^<]+)(?:>(.)</\1>|\s+/>)$/删除代码\注释 (?<!http:|\S)//.Unicode编码中的汉字范围 /^[\u2E80-\u9FFF]+/


由于正则表达式比较晦涩,难以记忆,所以在更多的情况下进行爬虫时使用的是 xpath、css 选择器。在编写爬虫时,并无规定章法(习惯什么用什么,想用什么用什么,能用什么用什么)。


下面举两个数据提取的整合方式如下:


案例 1:由 xpath 提取该标签下的文本内容,通过正则提取价格的数字部分 ['99.00', '88.00', '80.00']


selector = response.css('ul.pager li.next a::attr(href)').extract()#通过 css 选取目标范围 selector.xpath('.//li/b/text()').re('\d+.\d+')


案例 2:#套路于上一个例子是一样的,通过字典的形式进行数据封装,正则数据过滤在封装数据时一同进行。selector = response.css('ul.pager li.next a::attr(href)').extract()#通过 css 选取目标范围 selector.xpath('.//li/b/text()').re('\d+.\d+')#由 xpath 提取该标签下的文本内容,通过正则提取价格的数字部分 ['99.00', '88.00', '80.00']#举例如下:def get_infos(html):html = etree.HTML(html)infos = response.css('ul.pager li.next a::attr(href)').extract()for info in infos:exp_name = info.xpath('./a/text()')[0]url_info = info.xpath('./a/@href')[0]time_day = info.xpath('./span[@class="y-right"]/text()')[0]data = {'漏洞名称': exp_name.replace('\n', '').replace(' ', '').re('\d+.\d+'),'漏洞地址': 'https://help.xxxx.com{}'.format(url_info),'日期': time_day.re('\d+.\d+'),#'时间': time,}print(data)print('\n')


JSON 数据提取


JSON 是一种轻量级的数据交换格式。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。在易于人阅读和编写的同时,JSON 也易于机器解析和生成,并能有效地提升网络传输效率。


一般在爬取动态页面时才会使用到 JSON 提取数据。


我们以https://www.cnbeta.com/为例,爬取页面的内容,如图 10、11 所示:


这是一个动态页面,动态页面通过 json 进行传输数据,所以我们对动态页面的爬取就是对动态页面的 js 的提取。该网站不仅对 referer 和 UA 进行了校验,同时还在页面中通过 JavaScript 语句进行动态链接请求,从而导致不能动态获取页面中的信息,所以只是展示一个 jsonpath 提取 json 数据的小栗子,代码示例如下。


#下面据一个提取 json 数据的小例子 Import jsonpathdef get_infos(html):html = json.loads(html)list_html = jsonpath.jsonpath(html,'..post_title')]title = str(title)title=title[3:-3]first_url=jsonpath.jsonpath(info,'..post_date')first_content=jsonpath.jsonpath(info,'$..content')data = {'安全讯息': title,'讯息地址': 'https://s.tencent.com{}'.format(first_url),'日期': time,'内容简介': first_content,}print(data)print('\n')


4IP 代理


大家可能都有过给浏览器设置 HTTP 代理的经验,HTTP 代理服务器可以比作客户端与 Web 服务器(网站)之间的一个信息中转站,客户端发送的 HTTP 请求和 Web 服务器返回的 HTTP 响应通过代理服务器转发给对方,如图 12 所示:


爬虫程序在爬取某些网站时也需要使用代理,常见原因可包括:• 由于网络环境因素,直接爬取速度太慢,使用代理可提高爬取速度。• 某些网站对用户的访问速度进行限制,爬取过快会被封禁 ip,使用代理的话可以防止被封禁。• 由于地方法律或政治原因,某些网站无法直接访问,使用代理则可以绕过访问限制。


通过 python 查看 IP 的代码如下所示:


import requestsheaders = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36'}url = 'http://icanhazip.com/'response = requests.get(url,headers=headers)ip = response.text.replace('\n','')print(ip)想要更换 IP,就需要使用到大量的 IP。


首先付费版代理 IP 有如:• 芝麻代理http://www.zhimaruanjian.com• 阿布云:https://center.abuyun.com/login• 代理云http://www.dailiyun.com


免费版代理 IP 有如:• http://www.data5u.com/http://www.66ip.cn/http://www.goubanjia.com/http://www.66ip.cn/


编写爬虫爬取上面的 IP、端口信息的结果如图 13 所示:


IP 代理使用如下的代码示例如下:


import requests

代理服务器

proxyHost = "http-dyn.abuyun.com"proxyPort = "9020"

代理隧道验证信息

proxyUser = ''proxyPass = ''proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {"host": proxyHost,"port": proxyPort,"user": proxyUser,"pass": proxyPass,}#可以读取文件批量便利 proxies = {"http": proxyMeta,"https": proxyMeta,}headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36'}url = 'http://icanhazip.com/'response = requests.get(url,headers=headers,proxies=proxies)ip = response.text.replace('\n','')print(“成功获取到代理”,ip)


上述代码也可以用来检测爬取到的代理能否正常使用。


5API 接口调用


API 中文名叫【编程应用接口】,换句话说,这是一种接口,在爬虫中也被广泛使用。


爬虫是通过访问其他网站,然后从中提取结构化的数据,进行抓包分析,正则,bs4 ,js 逆向等等,整体比较麻烦。相比之下,API 接口的调用就会方便得多。如果对方开放了 API 接口,则可以考虑使用接口,这可达到事半功倍的效果,因为对方如果有 API 接口,说明对方有对外开放数据,那我们获得数据也就方便,只需要请求接口,得到返回的 json 数据即可,不用担心反爬。


大家常听到的 API 类型,应该是【天气预报 API】,【百度地图 API】之类的,现在有很多 API 服务,我们可以根据需求寻找对应的。


若遇到了 Ajax 动态加载的情况怎么办?这和前面通过 json 提取动态页面是一样的。


https://gank.io/api


可以看到调用 api 接口后,得到一个 json 数据,所以这里我们可以使用上文提到的 json 数据提取方法进行数据的提取。


6 法律法规


网络运营者采取自动化手段访问收集网站数据,不得妨碍网站正常运行;此类行为严重影响网站运行,如自动化访问收集流量超过网站日均流量三分之一,网站要求停止自动化访问收集时,应当停止。


以下是司法解释里面提到以下集中类型的数据,无论是“非法提供”和“非法获取”都可以入刑:


第一类:高度敏感信息,包括四种信息:行踪轨迹信息、通信内容、征信信息、财产信息。涉及高度敏感信息的违法活动,由于定罪门槛最低,因此严格限制在此四类,不做任何扩展;


第二类:敏感信息,即住宿信息、通信记录、健康生理信息、交易信息等其他可能影响人身、财产安全的公民个人信息。与第一类相比较,《解释》对第二类信息的界定仍留有空间,意味着在司法实践中,仍有可能会出现目前所列举之外的第二类信息类型;


第三类:其他个人信息。即上述第二、三类以外的个人信息。个人信息的类型是定罪量刑的重要依据。越敏感信息,达到定罪门槛的信息数量越少。

最后:点赞加关注楼主哦 私信我免费分享网络安全资料

发布于: 2021 年 04 月 22 日阅读数: 92
用户头像

Thrash

关注

还未添加个人签名 2021.04.06 加入

还未添加个人简介

评论

发布
暂无评论
一入爬虫深似海,从此早睡是路人