数据获取——爬虫(下)

5.静态、动态网站的区别和应对

5.1区分静态、动态网站

  静态网站的特点:

    静态网站是最初的建站方式,浏览者所看到的每个页面是建站者上传到服务器上的一个 html ( htm )文件,这种网站每增加、删除、修改一个页面,都必须重新对服务器的文件进行一次下载上传。

    网页内容一经发布到网站服务器上,无论是否有用户访问,每个静态网页的内容都是保存在网站服务器上的,也就是说,静态网页是实实在在保存在服务器上的文件,每个网页都是一个独立的文件。

  • 静态网页的内容相对稳定,因此容易被搜索引擎检索。

  • 静态网页没有数据库的支持,在网站制作和维护方面工作量较大,因此当网站信息量很大时完全依靠静态网页制作方式比较困难。

  • 静态网页的交互性较差,在功能方面有较大的限制。

    通俗来说,静态网页是指存放在服务器文件系统中实实在在的HTML文件。当用户在浏览器中输入页面的URL,然后回车,浏览器就会将对应的HTML文件下载、渲染并呈现在窗口中。早期的网站通常都是由静态页面制作的。

              

动态网站的特点:

    动态网站在页面里嵌套了程序,这种网站对一些框架相同、更新较快的信息页面进行内容与形式的分离,将信息内容以记录的形式存入网站的数据库中,以便于网站各处的调用。

    动态网页是相对于静态网页而言的。当浏览器请求服务器的某个页面时,服务器根据当前时间、环境参数、数据库操作等动态的生成HTML页面,然后在发送给浏览器(后面的处理就跟静态网页一样了)。

    很明显,动态网页中的“动态"是指服务器端页面的动态生成,相反,"静态"则指页面是实实在在的、独立的文件。

这里说的动态网页,与网页上的各种动画、滚动字幕等视觉上的 “ 动态效果 ” 没有直接关系,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,采用动态网站技术生成的网页都称为动态网页。

    从网站浏览者的角度来看,无论是动态网页还是静态网页,都可以展示基本的文字和图片信息,但从网站开发、管理、维护的角度来看就有很大的差别。
动态网页的特点归纳如下:

  • 动态网页以数据库技术为基础,可以大大降低网站维护的工作量 ;

  • 采用动态网页技术的网站可以实现更多的功能,如用户注册、用户登录、在线调查、用户管理、订单管理等等 ;

  • 动态网页实际上并不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页 ;

注意:

    动态页面技术是与静态页面技术相对应的,也就是说,网页URL的后缀不是.htm、.html、.shtml、.xml等静态网页的常见形式,而是以.asp、.jsp、.php、.perl、.cgi等形式为后缀,并且在动态网页网址中有一个标志性的符号——“? "。

    这里说的动态网页,与网页上的各种动画、滚动字幕等视觉上的“动态效果"没有直接关系,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,采用动态网站技术生成的网页都称为动态网页。

 

 5.2静态网站解析流程

  ① 你要爬取的网站是什么?

  ② 你要爬取页面上的哪些信息?

  ③ 页面是 “静态网页”,还是“动态网页”?

  那么它们的区别就在于: 静态网页中的数据,是一次性给你。动态网页中的数据,是随着页面一步步加载出来,而逐步呈现的,也就是你用静态网页的爬虫技术,无法获取到里面所有的数据。

实例提取电视台收视率:

import csv # 用于数据存储
import requests # 用于请求网页
import chardet # 用于修改编码
import re # 用于提取数据
from lxml import etree # 解析数据的库
import time # 可以粗糙模拟人为请求网页的速度
import warnings # 忽略代码运行时候的警告信息
warnings.filterwarnings("ignore")

def get_data(url):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
    rqg = requests.get(url, headers=headers, verify=False) # a
    rqg.encoding = chardet.detect(rqg.content)['encoding'] # b
    html = etree.HTML(rqg.text)

    # 1. 标题
    title = html.xpath('//header[@class="entry-header"]/table/tbody/tr/td[2]/font/h2/a/@title')
    # 2. 发布时间
    date = html.xpath('//header[@class="entry-header"]/table/tbody/tr/td[2]/div/time/text()')
    # 3. 链接
    link = html.xpath('//header[@class="entry-header"]/table/tbody/tr/td[2]/font/h2/a/@href')
    
    return title, date, link

def main():
    x = "http://www.tvtv.hk/archives/category/tv/page/"
    url_list = [x + str(i) for i in range(1,11)] 

    headers = ['标题','发布时间','链接']
    values = []
    titles = []
    dates = []
    links = []
    for url in url_list:
        print('>> 正获取: ',url)
        title, date, link = get_data(url)
        for t in title:
            titles.append(t)
        for d in date:
            dates.append(d)
        for l in link:
            links.append(l)
        
        time.sleep(3)  # 加时间延迟,减少访问频率

    for i in range(len(titles)):
        value = [titles[i],dates[i],links[i]]
        values.append(value)
    
    with open('电视台.csv','w',newline='') as fp:
        # 获取对象
        writer = csv.writer(fp)
        # 写入数据
        writer.writerow(headers) #写入表头
        writer.writerows(values) # 写入数据

if __name__=='__main__':
    main()
View Code

6.动态网站分析

  常见的动态网页技术:JavaScript、Ajax、DHTML

  使用动态加载的网站,用Python解决有如下几种途径:

  • 直接破解JavaScript代码里采集内容,即js逆向;

  • 抓包分析,查看截图的请求响应信息,伪造请求,实现响应的获取,即找到真实加载数据的动态链接;

  • 用Python的第三方库运行JavaScript,直接采集你在浏览器里看到的页面,即模拟登录;

6.1Ajax加载的动态网站分析

  有时候我们在用 requests 抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用 requests 得到的结果并没有。这是因为 requests 获取的都是原始的 HTML 文档,而浏览器中的页面则是经过 JavaScript 处理数据后生成的结果,这些数据的来源有多种,可能是通过 Ajax 加载的,可能是包含在 HTML 文档中的,也可能是经过 JavaScript 和特定算法计算后生成的。

  对于第一种情况,数据加载是一种异步加载方式,原始的页面最初不会包含某些数据,原始页面加载完后,会再向服务器请求某个接口获取数据,然后数据才被处理从而呈现到网页上,这其实就是发送了一个 Ajax 请求。

  所以如果遇到这样的页面,直接利用 requests 等库来抓取原始页面,是无法获取到有效数据的,这时需要分析网页后台向接口发送的 Ajax 请求,如果可以用 requests 来模拟 Ajax 请求,那么就可以成功抓取了。

import requests

headers = {
    'authority': 'api.qimai.cn',
    'sec-ch-ua': '"Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
    'sec-ch-ua-platform': '"Windows"',
    'origin': 'https://www.qimai.cn',
    'sec-fetch-site': 'same-site',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://www.qimai.cn/',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cookie': 'qm_check=SxJXQEUSChd2fHd1dRQQeV5EVVwcEHxZRlVVGGYREGV4dBB3QlRHWllaQxQOAgAQdFlCVVZDAXQIARROQ28FbwAQQEZoB28JHBR8A3QBAR0CAhsFAh4IBhoMBwAIGRIcElZfV1NSEg4aABwAHAAcABkHEE0%3D; gr_user_id=9ef08b21-8dd7-45f0-8c40-88996def62ec; USERINFO=zcXe0A9c7kmLDlPofA%2FnW6%2Fi0Vnf0iA1hg7SRijWXCD8N4AMklWRp4k9WlYvFCkziUdIlH7KTirUSklRPhSZGHLBY3fxLkORNX3KOso0WSnvf9i9KuRh4V8ddjeG0v%2BdSSm08lrJ55qInpKRd8%2BOzA%3D%3D; AUTHKEY=snHdCWmpZLSo9%2BAU1RQgKbDLcKvIfHg%2FUKgzMC92wsIUzanyQBD529MAujOMU%2BWyN9il0RH0o%2BycPNGb6jDmvbP2Uj5w1ydWA%2FteweJu0ziZ6TbqfL%2Bs%2FA%3D%3D; ada35577182650f1_gr_last_sent_cs1=qm10437503601; aso_ucenter=360bynVy6wNu9y4%2BH0gQasBLv2hH72JBvq3j2Q59OpTYoSF62HCcKfBwHaSk3sZn4A; PHPSESSID=p34ufc1vdab8q2edo34diq3rdc; ada35577182650f1_gr_session_id=922e8346-72fe-45be-b349-54deb6a8e6f5; ada35577182650f1_gr_last_sent_sid_with_cs1=922e8346-72fe-45be-b349-54deb6a8e6f5; ada35577182650f1_gr_session_id_922e8346-72fe-45be-b349-54deb6a8e6f5=true; tgw_l7_route=d09474674af82c17375cfcdd775c0c28; synct=1634137296.468; syncd=823; ada35577182650f1_gr_cs1=qm10437503601',
}

params = (
    ('analysis', 'dQ59QSxadUR9ZHFEdTB6QipZcBJSd35FUWhyVwYFDQh0FU5CUV5bH1leXAFPaAhBRU5SQlFeVG9ZXEsGeEcFB1gAAQEGBQEDCVF3G1U='),
    ('brand', 'all'),
    ('country', 'cn'),
    ('device', 'iphone'),
    ('genre', '36'),
    ('date', '2021-10-13'),
    ('page', '2'),
)
try:
    response = requests.get('https://api.qimai.cn/rank/indexPlus/brand_id/1', headers=headers, params=params)
    if response.status_code == 200:
        print('请求成功')
        print(response.json())
except requests.ConnectionError as e:
    print('Error', e.args)

lists = response.json()['list']

results = []
for i in lists:
    result = {}
    result['APP'] = i['appInfo']['appName']
    result['类型'] = i['genre']
    result['公司'] = i['appInfo']['publisher']
    result['排名'] = i['index']
    print(result)
    results.append(result)
View Code

7.反爬

  因为爬虫技术造成的大量IP访问网站侵占带宽资源、以及用户隐私和知识产权等危害,很多互联网企业都会花大力气进行“反爬虫”。爬虫会遭遇比如被网站封IP、比如各种奇怪的验证码、userAgent访问限制、各种动态加载、post请求参数动态变化、禁止页面调试等都有可能出现。

  常见的反爬虫措施有:

  • 登录验证、验证码、滑块
  • 登录请求参数token
  • 通过Headers反爬虫
  • 基于用户行为反爬虫
  • 基于动态页面的反爬虫
  • 字体反爬
  • .......

  反反爬的主要思路:尽可能的去模拟浏览器,浏览器在如何操作,代码中就如何去实现。

7.1请求头:User-agent

  在这里的User-Agent可以使用多个随机的,意识就是假如你请求20次,你可以自己构造多个不同的User-Agent随机使用一次不重样的,防止过于频繁,这也是常见的方式。

  1、可以使用fake-useragent库来实现随机更换User-Agent

  2、自行从这个网站收集: http://useragent.kuzhazha.com/

  3、自行构建,如下

import random
def get_ua():
    first_num = random.randint(55, 62)
    third_num = random.randint(0, 3200)
    fourth_num = random.randint(0, 140)
    os_type = [
        '(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)',
        '(Macintosh; Intel Mac OS X 10_12_6)'
    ]
    chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)

    ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36',
                   '(KHTML, like Gecko)', chrome_version, 'Safari/537.36']
                  )
    return ua
print(get_ua())
View Code

7.2 通过referer字段或者是其他字段来反爬

  反爬原理:爬虫默认情况下不会带上referer字段
  解决方法:添加referer字段

7.3通过cookie来反爬

  如果目标网站不需要登录 每次请求带上前一次返回的cookie,比如requests模块的session 如果目标网站需要登录,
则准备多个账号,通过一个程序获取账号对应的cookie,组成cookie池,其他程序使用这些cookie.

7.4通过js来反爬

  普通的爬虫默认情况下无法执行js,获取js执行之后的结果,所以很多时候对方服务器会通过js的技术实现反爬

  1.找到debug的函数,禁止调用它,我们就可以正常调试了

    

   2.通过js生成了请求参数

    

  解决方法:分析js,观察加密的实现过程,这里就涉及到js逆向的知识了,或者使用selenium动态加载来实现,但这种方法局限性很大

   3.通过js实现了数据的加密

    

   解决方法:分析js,观察加密的实现过程,通过js2py获取js的执行结果,或者使用selenium来实现

7.5通过验证码来反爬

  反爬原理:对方服务器通过弹出验证码强制验证用户浏览行为

  解决方法:打码平台或者是机器学习的方法识别验证码,其中打码平台廉价易用,更值得推荐,不过如果是遇到简单的数字验证码或者滑块都是可以自行去解决的。

参考链接:   爬虫大佬 - Heywhale.com

       https://www.cnblogs.com/Amy-is-a-fish-yeah/p/11788464.html

posted @ 2022-03-27 21:37  hungry_J  阅读(26)  评论(0)    收藏  举报