【VSRC唯科普】避开采集陷阱(第12/14篇)

百家 作者:唯品会安全 2020-03-31 16:43:26

鸣 谢



VSRC感谢业界小伙伴——Mils 投稿精品科普类文章。VSRC欢迎精品原创类文章投稿,优秀文章一旦采纳发布,将有好礼相送,我们已为您准备好了丰富的奖品!

(活动最终解释权归VSRC所有)



一般的,一个成熟的商业化网站,为了防止数据被自动化工具所采集,会对访问浏览器的行为,进行判断,网站会区分访问行为是正常用户所发起的,还是自动化程序或机器人所为,一旦发现非人为操作,则通常会进行拦截。而在数据采集期间,为了防止我们的自动化工具,被网站轻易的识别和拦截,今天的唯科普,将主要介绍以下三种方式,可以使得自动化程序对浏览器的访问行为,更接近正常用户,从而避免被网站拦截:

方法1、修改User Agent

方法2、处理Cookies

方法3、避免蜜罐




方法1.修改请求头User Agent

在唯科普9里面,我们曾经使用requests模块处理网站的表单信息,并且我们也知道了requests模块是一个设置请求头的利器。HTTP的请求头指的是在每次向网络服务器发送请求时,传递的一组属性和配置信息。HTTP定义了十几种请求头类型,其中包括以下七个常用字段,这七个常用字段会被大多数浏览器用来初始化网络请求:

  •  Host

  •  Connection

  •  Accept

  •  User-Agent

  •  Referrer

  •  Accept-Encoding

  •  Accept-Language

经典的Python爬虫在使用urllib标准库时,都会发送如下的请求头:

  •  Accept-Encoding

  •  User-Agent


以下是一些Andriod、Firefox、Google Chrome、iOS的常用User Agent示例:

1.Android
Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19
Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

2.Firefox
Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0

3.Google Chrome
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19

4.iOS
Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36

如果不加以修饰,默认的,使用Python爬虫的请求头则直接会显示带有Python版本字样的User-Agent,类似这样的请求,就会很容易被网站的反爬虫检测机制给拦截掉。而请求头可以使用requests模块进行自定义,以 https://www.whatismybrowser.com/ 网站为例,该网站可以帮助我们在线测试浏览器的属性,我们可以通过程序模拟来采集这个网站的信息,验证浏览器Cookie设置:

import requests
from bs4 import BeautifulSoup

session = requests.Session()
headers = {
    "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
    "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/wepp,*/*;q=0.8"
}
url = "https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending"
req = session.get(url,headers=headers)
bsObj = BeautifulSoup(req.text,"html.parser")
print (bsObj.find("table",{"class":"table-striped"}).get_text)

最终输出结果中的请求头,与应用程序中设置的headers是一样的。 




方法2.处理Cookies

网站会使用cookie跟踪你访问的过程,如果发现自动化爬虫等异常行为,就会中断你的访问,比如特别快速的填写表单,或者浏览大量页面,虽然这些行为可以通过关闭并重新连接或改变IP地址来伪装,但是如果Cookie暴露了身份,再多努力也是白费。而正确的处理Cookie可以避免许多采集问题,当你在采集一个或几个目标网站时,建议检查这些网站生成的cookie,然后想下哪个cookie是需要爬虫处理的。有一些浏览器插件可以为你显示访问网站和离开网站时cookie是如何设置的。例如EditThisCookie就是一个非常好用的Chrome的浏览器插件之一。由于requests模块不能执行JavaScript,所以requests不能处理很多新式的跟踪软件生成的cookie,比如Google Analytics,只有当客户端脚本执行之后才设置cookie,或者用户在浏览页面时基于事件产生cookie,比如点击按钮。为了处理这些动作时,便会需要用到Selenium以及WebDriver。我们可以以http://pythonscraping.com为例,演示下如何调用WebDriver的GET方法来查看Cookie,示例代码如下:

from selenium import webdriver
exec_path = "C:\chromedriver.exe"
url = "http://pythonscraping.com/"
driver = webdriver.Chrome(executable_path=exec_path)
driver.get(url)
driver.implicitly_wait(1)
print (driver.get_cookies())

得到的返回信息如下,这样就能得到一个非常典型的Google Analytics的Cookie列表:

C:\Python37-x64\python.exe D:/phpStudy/WWW/VSRC_POP/CH12/webdriver_get_cookie.py
[{'domain''.pythonscraping.com''expiry'15****7'httpOnly'False'name''_gid''path''/''secure'False'value''GA1.2.5****03.158*****98'}, {'domain''.pythonscraping.com''expiry'164****97'httpOnly'False'name''_ga''path''/''secure'False'value''GA1.2.186****848.158****98'}, {'domain''.pythonscraping.com''expiry'158****57'httpOnly'False'name''_gat''path''/''secure'False'value''1'}, {'domain''pythonscraping.com''httpOnly'False'name''has_js''path''/''secure'False'value''1'}]

Process finished with exit code 0

另外还可以调用delete_cookie(),add_cookie()和delete_all_cookies()的方法来处理cookie,还可以保存cookie以备其他网络爬虫使用。示例如下:

from selenium import webdriver

exec_path = "C:\chromedriver.exe"
url = "http://pythonscraping.com/"

driver1 = webdriver.Chrome(executable_path=exec_path)
driver1.get(url)
driver1.implicitly_wait(1)
print ("driver1 : ",driver1.get_cookies())

savedCookies = driver1.get_cookies()

driver2 = webdriver.Chrome(executable_path=exec_path)
driver2.get(url)
driver2.delete_all_cookies()
for cookie in savedCookies:
    driver2.add_cookie(cookie)
driver2.get(url)
driver2.implicitly_wait(1)
print ("driver2 : ",driver2.get_cookies())

在这个例子中,第一个webdriver1获取了一个网站,打印cookie并把他们保存到变量savedCookies里。第二个webdriver2加载同一个网站,删除所有cookie,然后替换成第一个webdriver1得到的cookie,当再次加载这个页面时,两组cookie的时间戳,源代码及其他信息完全一致。于是,从Google Analytics的角度看,就会认为第二个webdriver和第一个webdriver是完全一样的。 




方法3.避免蜜罐

虽然在进行网络数据采集时候用CSS属性区分有用信息和无用信息会比较容易,比如通过读取id和class标签获取信息,但是这么做有时也会出问题,如果网络表单的一个字段通过CSS设置成了对用户不可见,那么可以认为普通用户访问网站的时候不能填写这个字段,因为他没有显示在浏览器上,如果这个字段被填写了,就可能是机器人干的,因此这个提交会失效。这种手段不仅可以应用在网站的表单上,还可以应用在链接、图片、以及一些可以被机器人读取,但普通用户在浏览器上却看不到的任何内容上面,访问者如果访问了网站上的“隐含”内容,就会触发服务器脚本封杀这个用户的IP地址,把这个用户提出网站,或采取其他措施禁止这个用户接入网站。

在这个页面中,http://pythonscraping.com/pages/itsatrap.html,包含了两个链接,一个通过CSS隐含了,另外一个是可见的,并且页面上还包含了两个隐含字段:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>A bot-proof form</title>
</head>
<style>
    body {
        overflow-x:hidden;
    }
    .customHidden {
        position:absolute;
        right:50000px;
    }
</style>
<body>
    <h2>A bot-proof form</h2>
    <a href="http://pythonscraping.com/dontgohere" style="display:none;">Go here!</a>
    <a href="http://pythonscraping.com">Click me!</a>
    <form>
        <input type="hidden" name="phone" value="valueShouldNotBeModified"/><p/>
        <input type="text" name="email" class="customHidden" value="intentionallyBlank"/><p/>
        <input type="text" name="firstName"/><p/>
        <input type="text" name="lastName"/><p/>
        <input type="submit" value="Submit"/><p/>
    </form>
</body>
</html>

这三个元素通过不同的方式对用户隐藏:

  • 第一个链接是通过简单的CSS属性设置display:none进行隐藏

  • 电话号码字段 name="phone"是一个隐含的输入字段

  • 邮箱地址字段 name="email"是一个将元素向右移动50000像素并隐藏滚动条

因为Selenium可以获取访问页面的内容,所以他可以区分页面上的可见元素与隐含元素。通过is_display()可以判断元素在页面上是否可见。例如,以下这段代码显示就是可以获取前面那个页面的内容,然后查找隐含链接和隐含输入字段:

from selenium import webdriver
from selenium.webdriver.remote.webelement import WebElement

exec_path = "C:\chromedriver.exe"
driver = webdriver.Chrome(executable_path=exec_path)
driver.get("http://pythonscraping.com/pages/itsatrap.html")

links = driver.find_elements_by_tag_name("a")
for link in links:
    if not link.is_displayed():
        print ("The link" + link.get_attribute("href")+ "is a trap")

fields = driver.find_elements_by_tag_name("input")
for field in fields:
    if not field.is_displayed():
        print ("Do not change value of " + field.get_attribute("name"))

Selenium抓出了每一个隐含的链接字段,结果如图所示:

虽然我们通常不太可能会去访问那些隐藏的链接,但是在提交表单之前,记得确认一下那些已经在表单中、准备提交的隐含字段的值(或者让Selenium为你自动提交)。




参考资料

1、https://www.w3school.com.cn

2、https://www.python.org/

3、《Web Scraping with Python》






唯科普 | 《数据采集》目录

A.K.A "小白终结者"系列

第1篇、初识网络通信

第2篇、来点更精彩的正则表达式吧

第3篇、多种数据采集方式

第4篇、让我们加入点API

第5篇、数据的存储

第6篇、文档读取

第7篇、数据清洗

第8篇、自然语言处理之概括数据(上篇)

第8篇、自然语言处理之马尔可夫模型(中篇)

第8篇、自然语言处理之六度分割终极篇(下篇)

第9篇、穿越网页表单与登录窗口的采集

第10篇、关于数据的采集姿势

第11篇、图像识别与文字处理

第12篇、避开采集的陷阱

第13篇、用自动化程序测试网站

第14篇、远程采集




精彩原创文章投稿有惊喜!

欢迎投稿!

VSRC欢迎精品原创类文章投稿,优秀文章一旦采纳发布,将为您准备的丰富奖金税后1000元现金或等值礼品,上不封顶!如若是安全文章连载,奖金更加丰厚,税后10000元或等值礼品,上不封顶!还可领取精美礼品!可点击“阅读原文”了解规则。(最终奖励以文章质量为准。活动最终解释权归VSRC所有)



我们聆听您宝贵建议


不知道,大家都喜欢阅读哪些类型的信息安全文章?

不知道,大家都希望我们更新关于哪些主题的干货?

现在起,只要您有任何想法或建议,欢迎直接回复本公众号留言!

精彩留言互动的热心用户,将有机会获得VSRC赠送的精美奖品一份!

同时,我们也会根据大家反馈的建议,选取热门话题,进行原创发布!


点击阅读原文进入   【VSRC征稿】宅家副业攻略请查收!



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接