相思资源网 Design By www.200059.com

常见的反爬机制及处理方式

1、Headers反爬虫 :Cookie、Referer、User-Agent

解决方案: 通过F12获取headers,传给requests.get()方法

2、IP限制 :网站根据IP地址访问频率进行反爬,短时间内进制IP访问

解决方案:

1、构造自己IP代理池,每次访问随机选择代理,经常更新代理池

2、购买开放代理或私密代理IP

3、降低爬取的速度

3、User-Agent限制 :类似于IP限制

解决方案: 构造自己的User-Agent池,每次访问随机选择

5、对查询参数或Form表单数据认证(salt、sign)

解决方案: 找到JS文件,分析JS处理方法,用Python按同样方式处理

6、对响应内容做处理

解决方案: 打印并查看响应内容,用xpath或正则做处理

python中正则处理headers和formdata

1、pycharm进入方法 :Ctrl + r ,选中 Regex

2、处理headers和formdata

(.*): (.*)

"1":"1":"2",

3、点击 Replace All

民政部网站数据抓取

目标: 抓取最新中华人民共和国县以上行政区划代码

URL: http://www.mca.gov.cn/article/sj/xzqh/2019/ - 民政数据 - 行政区划代码

实现步骤

1、从民政数据网站中提取最新行政区划代码链接

最新的在上面,命名格式: 2019年X月中华人民共和国县以上行政区划代码

import requests
from lxml import etree
import re
"artitlelist"]')
"htmlcode">
# 爬取二级“假”链接
two_html = requests.get(two_link, headers=headers).text
# 从二级页面的响应中提取真实的链接(此处为JS动态加载跳转的地址)
new_two_link = re.findall(r'window.location.href="(.*" rel="external nofollow" rel="external nofollow" ', two_html, re.S)[0]

3、在数据库表中查询此条链接是否已经爬取,建立增量爬虫

数据库中建立version表,存储爬取的链接

每次执行程序和version表中记录核对,查看是否已经爬取过

cursor.execute('select * from version')
result = self.cursor.fetchall()
if result:
  if result[-1][0] == two_link:
    print('已是最新')
  else:
    # 有更新,开始抓取
    # 将链接再重新插入version表记录

4、代码实现

import requests
from lxml import etree
import re
import pymysql
class GovementSpider(object):
  def __init__(self):
    self.url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/'
    self.headers = {'User-Agent': 'Mozilla/5.0'}
    # 创建2个对象
    self.db = pymysql.connect('127.0.0.1', 'root', '123456', 'govdb', charset='utf8')
    self.cursor = self.db.cursor()
  # 获取假链接
  def get_false_link(self):
    html = requests.get(url=self.url, headers=self.headers).text
    # 此处隐藏了真实的二级页面的url链接,真实的在假的响应网页中,通过js脚本生成,
    # 假的链接在网页中可以访问,但是爬取到的内容却不是我们想要的
    parse_html = etree.HTML(html)
    a_list = parse_html.xpath('//a[@class="artitlelist"]')
    for a in a_list:
      # get()方法:获取某个属性的值
      title = a.get('title')
      if title.endswith('代码'):
        # 获取到第1个就停止即可,第1个永远是最新的链接
        false_link = 'http://www.mca.gov.cn' + a.get('href')
        print("二级“假”链接的网址为", false_link)
        break
    # 提取真链接
    self.incr_spider(false_link)
  # 增量爬取函数
  def incr_spider(self, false_link):
    self.cursor.execute('select url from version where url=%s', [false_link])
    # fetchall: (('http://xxxx.html',),)
    result = self.cursor.fetchall()

    # not result:代表数据库version表中无数据
    if not result:
      self.get_true_link(false_link)
      # 可选操作: 数据库version表中只保留最新1条数据
      self.cursor.execute("delete from version")

      # 把爬取后的url插入到version表中
      self.cursor.execute('insert into version values(%s)', [false_link])
      self.db.commit()
    else:
      print('数据已是最新,无须爬取')
  # 获取真链接
  def get_true_link(self, false_link):
    # 先获取假链接的响应,然后根据响应获取真链接
    html = requests.get(url=false_link, headers=self.headers).text
    # 从二级页面的响应中提取真实的链接(此处为JS动态加载跳转的地址)
    re_bds = r'window.location.href="(.*" rel="external nofollow" rel="external nofollow" '
    pattern = re.compile(re_bds, re.S)
    true_link = pattern.findall(html)[0]

    self.save_data(true_link) # 提取真链接的数据
  # 用xpath直接提取数据
  def save_data(self, true_link):
    html = requests.get(url=true_link, headers=self.headers).text

    # 基准xpath,提取每个信息的节点列表对象
    parse_html = etree.HTML(html)
    tr_list = parse_html.xpath('//tr[@height="19"]')
    for tr in tr_list:
      code = tr.xpath('./td[2]/text()')[0].strip() # 行政区划代码
      name = tr.xpath('./td[3]/text()')[0].strip() # 单位名称
      print(name, code)

  # 主函数
  def main(self):
    self.get_false_link()
if __name__ == '__main__':
  spider = GovementSpider()
  spider.main()

动态加载数据抓取-Ajax

特点

右键 -> 查看网页源码中没有具体数据

滚动鼠标滑轮或其他动作时加载

抓取

F12打开控制台,选择XHR异步加载数据包,找到页面动作抓取网络数据包

通过XHR-->Header-->General-->Request URL,获取json文件URL地址

通过XHR-->Header-->Query String Parameters(查询参数)

豆瓣电影数据抓取案例

目标

地址: 豆瓣电影 - 排行榜 - 剧情

https://movie.douban.com/typerank"_blank" href="https://movie.douban.com/typerank" rel="external nofollow" >type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=

目标: 爬取电影名称、电影评分

F12抓包(XHR)

1、Request URL(基准URL地址) :https://movie.douban.com/j/chart/top_list"htmlcode">

# 查询参数如下:
type: 13 # 电影类型
interval_id: 100:90
action: '[{},{},{}]'
start: 0 # 每次加载电影的起始索引值
limit: 20 # 每次加载的电影数量

json文件在以下地址:

基准URL地址+查询参数

'https://movie.douban.com/j/chart/top_list"htmlcode">

import requests
import time
from fake_useragent import UserAgent
class DoubanSpider(object):
  def __init__(self):
    self.base_url = 'https://movie.douban.com/j/chart/top_list"_blank" href="https://careers.tencent.com/search.html" rel="external nofollow" >https://careers.tencent.com/search.html

目标: 职位名称、工作职责、岗位要求

要求与分析

通过查看网页源码,得知所需数据均为 Ajax 动态加载

通过F12抓取网络数据包,进行分析

一级页面抓取数据: 职位名称

二级页面抓取数据: 工作职责、岗位要求

一级页面json地址(pageIndex在变,timestamp未检查)

https://careers.tencent.com/tencentcareer/api/post/Query"htmlcode">

ua_list = [
 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)',
]
import time
import json
import random
import requests
from useragents import ua_list
class TencentSpider(object):
  def __init__(self):
    self.one_url = 'https://careers.tencent.com/tencentcareer/api/post/Query?timestamp=1563912271089&countryId=&cityId=&bgIds=&productId=&categoryId=&parentCategoryId=&attrId=&keyword=&pageIndex={}&pageSize=10&language=zh-cn&area=cn'
    self.two_url = 'https://careers.tencent.com/tencentcareer/api/post/ByPostId?timestamp=1563912374645&postId={}&language=zh-cn'
    self.f = open('tencent.json', 'a') # 打开文件
    self.item_list = [] # 存放抓取的item字典数据
  # 获取响应内容函数
  def get_page(self, url):
    headers = {'User-Agent': random.choice(ua_list)}
    html = requests.get(url=url, headers=headers).text
    html = json.loads(html) # json格式字符串转为Python数据类型
    return html
  # 主线函数: 获取所有数据
  def parse_page(self, one_url):
    html = self.get_page(one_url)
    item = {}
    for job in html['Data']['Posts']:
      item['name'] = job['RecruitPostName'] # 名称
      post_id = job['PostId'] # postId,拿postid为了拼接二级页面地址
      # 拼接二级地址,获取职责和要求
      two_url = self.two_url.format(post_id)
      item['duty'], item['require'] = self.parse_two_page(two_url)
      print(item)
      self.item_list.append(item) # 添加到大列表中
  # 解析二级页面函数
  def parse_two_page(self, two_url):
    html = self.get_page(two_url)
    duty = html['Data']['Responsibility'] # 工作责任
    duty = duty.replace('\r\n', '').replace('\n', '') # 去掉换行
    require = html['Data']['Requirement'] # 工作要求
    require = require.replace('\r\n', '').replace('\n', '') # 去掉换行
    return duty, require
  # 获取总页数
  def get_numbers(self):
    url = self.one_url.format(1)
    html = self.get_page(url)
    numbers = int(html['Data']['Count']) // 10 + 1 # 每页有10个推荐
    return numbers
  def main(self):
    number = self.get_numbers()
    for page in range(1, 3):
      one_url = self.one_url.format(page)
      self.parse_page(one_url)
    # 保存到本地json文件:json.dump
    json.dump(self.item_list, self.f, ensure_ascii=False)
    self.f.close()
if __name__ == '__main__':
  start = time.time()
  spider = TencentSpider()
  spider.main()
  end = time.time()
  print('执行时间:%.2f' % (end - start))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

标签:
python,爬取,ajax,动态加载网页

相思资源网 Design By www.200059.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
相思资源网 Design By www.200059.com

评论“python爬取Ajax动态加载网页过程解析”

暂无python爬取Ajax动态加载网页过程解析的评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。