亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python爬取Ajax動態加載網頁過程解析

系統 1795 0

常見的反爬機制及處理方式

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
?
url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'}
html = requests.get(url, headers=headers).text
parse_html = etree.HTML(html)
article_list = parse_html.xpath('//a[@class="artitlelist"]')
?
for article in article_list:
  title = article.xpath('./@title')[0]
  # 正則匹配title中包含這個字符串的鏈接
  if title.endswith('代碼'):
    # 獲取到第1個就停止即可,第1個永遠是最新的鏈接
    two_link = 'http://www.mca.gov.cn' + article.xpath('./@href')[0]
    print(two_link)
    break
          

2、從二級頁面鏈接中提取真實鏈接(反爬-響應網頁內容中嵌入JS,指向新的網頁鏈接)

向二級頁面鏈接發請求得到響應內容,并查看嵌入的JS代碼

正則提取真實的二級頁面鏈接

            
# 爬取二級“假”鏈接
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?

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?

2、Query String Paramaters(查詢參數)

            
# 查詢參數如下:
type: 13 # 電影類型
interval_id: 100:90
action: '[{},{},{}]'
start: 0 # 每次加載電影的起始索引值
limit: 20 # 每次加載的電影數量
          

json文件在以下地址:

基準URL地址+查詢參數

'https://movie.douban.com/j/chart/top_list?'+'type=11&interval_id=100%3A90&action=&start=20&limit=20'

代碼實現

            
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?'
    self.i = 0
  def get_html(self, params):
    headers = {'User-Agent': UserAgent().random}
    res = requests.get(url=self.base_url, params=params, headers=headers)
    res.encoding = 'utf-8'
    html = res.json() # 將json格式的字符串轉為python數據類型
    self.parse_html(html) # 直接調用解析函數
  def parse_html(self, html):
    # html: [{電影1信息},{電影2信息},{}]
    item = {}
    for one in html:
      item['name'] = one['title'] # 電影名
      item['score'] = one['score'] # 評分
      item['time'] = one['release_date'] # 打印測試
      # 打印顯示
      print(item)
      self.i += 1
  # 獲取電影總數
  def get_total(self, typ):
    # 異步動態加載的數據 都可以在XHR數據抓包
    url = 'https://movie.douban.com/j/chart/top_list_count?type={}&interval_id=100%3A90'.format(typ)
    ua = UserAgent()
    html = requests.get(url=url, headers={'User-Agent': ua.random}).json()
    total = html['total']

    return total

  def main(self):
    typ = input('請輸入電影類型(劇情|喜劇|動作):')
    typ_dict = {'劇情': '11', '喜劇': '24', '動作': '5'}
    typ = typ_dict[typ]
    total = self.get_total(typ) # 獲取該類型電影總數量

    for page in range(0, int(total), 20):
      params = {
        'type': typ,
        'interval_id': '100:90',
        'action': '',
        'start': str(page),
        'limit': '20'}
      self.get_html(params)
      time.sleep(1)
    print('爬取的電影的數量:', self.i)
if __name__ == '__main__':
  spider = DoubanSpider()
  spider.main()
          

騰訊招聘數據抓取(Ajax)

確定URL地址及目標

URL: 百度搜索騰訊招聘 - 查看工作崗位 https://careers.tencent.com/search.html

目標: 職位名稱、工作職責、崗位要求

要求與分析

通過查看網頁源碼,得知所需數據均為 Ajax 動態加載

通過F12抓取網絡數據包,進行分析

一級頁面抓取數據: 職位名稱

二級頁面抓取數據: 工作職責、崗位要求

一級頁面json地址(pageIndex在變,timestamp未檢查)

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

二級頁面地址(postId在變,在一級頁面中可拿到)

https://careers.tencent.com/tencentcareer/api/post/ByPostId?timestamp=1563912374645&postId={}&language=zh-cn

useragents.py文件

            
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))
          

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 蜜桃综合 | 在线观看久草 | 国产福利在线观看精品 | 爱久久www.35669 | 日韩国产欧美一区二区三区在线 | 二性视频 | jizz国产美女 | 亚洲伊人久久大香线蕉结合 | 亚洲成a人片毛片在线 | 欧美成人精品一区二三区在线观看 | 久久网站免费 | 国产成人精品精品欧美 | 高清视频 一区二区三区四区 | 欧美一级片在线视频 | 青青草免费视频在线播放 | 久草免费在线视频观看 | 欧美综合色另类图片区 | 亚洲精品tv久久久久久久久 | 久久91精品久久91综合 | 四虎精品成人免费影视 | 青草青草久热精品视频99 | 乱子伦有声小说mp3 仑乱高清在线一级播放 | 久草精品在线播放 | 高清国产一区 | 99网站在线观看 | 亚洲国产男人本色在线观看的a站 | 人人澡人人干 | 在线观看 亚洲 | 天天摸天天干天天操 | 亚洲人成一区二区三区 | 97精品国产自在现线免费 | 欧美高清视频www夜色资源 | 爱婷婷网站在线观看 | 亚洲国产精品网 | 久久精品免看国产成 | 视频1区| 波多野结衣在线观看3人 | 妞干网这里只有精品 | 免费一级毛片麻豆精品 | 色妞www精品视频 | 农村苗族一级特黄a大片 |