打開方式幾經常使用選項html
1、打開瀏覽器,F12打開控制檯,找到Network選項卡 2、控制檯經常使用選項 1、Network: 抓取網絡數據包 1、ALL: 抓取全部的網絡數據包 2、XHR:抓取異步加載的網絡數據包 3、JS : 抓取全部的JS文件 2、Sources: 格式化輸出並打斷點調試JavaScript代碼,助於分析爬蟲中一些參數 3、Console: 交互模式,可對JavaScript中的代碼進行測試 3、抓取具體網絡數據包後 1、單擊左側網絡數據包地址,進入數據包詳情,查看右側 2、右側: 1、Headers: 整個請求信息 General、Response Headers、Request Headers、Query String、Form Data 2、Preview: 對響應內容進行預覽 三、Response:響應內容
1.適用場景python
Post類型請求的網站mysql
2.參數-dataweb
response = requests.post(url,data=data,headers=headers) # data :post數據(Form表單數據-字典格式)
3.請求方式特色算法
GET請求 : 參數在URL地址中有顯示 POST請求: Form表單提交數據
1.目標sql
破解有道翻譯接口,抓取翻譯結果 # 結果展現 請輸入要翻譯的詞語: elephant 翻譯結果: 大象 ************************** 請輸入要翻譯的詞語: 喵喵叫 翻譯結果: mews
2.實現步驟數據庫
一、瀏覽器F12開啓網絡抓包,Network-All,頁面翻譯單詞後找Form表單數據 2、在頁面中多翻譯幾個單詞,觀察Form表單數據變化(有數據是加密字符串) 3、刷新有道翻譯頁面,抓取並分析JS代碼(本地JS加密) 4、找到JS加密算法,用Python按一樣方式加密生成加密數據 五、將Form表單數據處理爲字典,經過requests.post()的data參數發送
具體實現json
1.開啓F2抓包,找到Form表但數據以下:瀏覽器
i: 喵喵叫 from: AUTO to: AUTO smartresult: dict client: fanyideskweb salt: 15614112641250 sign: 94008208919faa19bd531acde36aac5d ts: 1561411264125 bv: f4d62a2579ebb44874d7ef93ba47e822 doctype: json version: 2.1 keyfrom: fanyi.web action: FY_BY_REALTlME
2.在頁面中多翻譯幾個單詞,觀察Form表單數據變化cookie
salt: 15614112641250 sign: 94008208919faa19bd531acde36aac5d ts: 1561411264125 bv: f4d62a2579ebb44874d7ef93ba47e822 # 可是bv的值不變
3.通常爲本地js文件加密,刷新頁面,找到js文件並分析JS代碼
# 方法1 Network - JS選項 - 搜索關鍵詞salt # 方法2 控制檯右上角 - Search - 搜索salt - 查看文件 - 格式化輸出 # 最終找到相關JS文件 : fanyi.min.js
4.打開JS文件,分析加密算法,用Python實現
# ts : 通過分析爲13位的時間戳,字符串類型 js代碼實現: "" + (new Date).getTime() python實現: str(int(time.time()*1000)) # salt : ts + 0-9之間的隨機數 js代碼實現: ts+parseInt(10 * Math.random(), 10); python實現: ts + str(randow.randint(0-9)) # sign(設置斷點調試,來查看 e 的值,發現 e 爲要翻譯的單詞) js代碼實現: n.md5("fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj") python實現: from hashlib import md5 string = "fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj" s = md5() s.update(string.encode()) sign = s.hexdigest() #bv 不變的值,不須要處理,直接複製
5.代碼實現
import requests import time import random from hashlib import md5 class YdSpider(): def __init__(self): # url必定爲爲F12抓到的headers->General->Request self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule' self.headers = { "Cookie": "OUTFOX_SEARCH_USER_ID=970246104@10.169.0.83; OUTFOX_SEARCH_USER_ID_NCOO=570559528.1224236; _ntes_nnid=96bc13a2f5ce64962adfd6a278467214,1551873108952; JSESSIONID=aaae9i7plXPlKaJH_gkYw; td_cookie=18446744072941336803; SESSION_FROM_COOKIE=unknown; ___rl__test__cookies=1565689460872", "Referer": "http://fanyi.youdao.com/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36", } # 獲取salt,sign,ts def get_salt_sign_ts(self, word): # ts ts = str(int(time.time() * 1000)) # salt salt = ts + str(random.randint(0, 9)) # sign string = "fanyideskweb" + word + salt + "n%A-rKaT5fb[Gy?;N5@Tj" s = md5() s.update(string.encode()) sign = s.hexdigest() return salt, sign, ts # 主函數 def attack_yd(self, word): # 先拿到salt,sign,ts salt, sign, ts = self.get_salt_sign_ts(word) # 定義form表單數據爲字典:data={} data = { 'i': word, 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': salt, 'sign': sign, 'ts': ts, 'bv': 'cf156b581152bd0b259b90070b1120e6', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web', 'action': 'FY_BY_REALTlME' } # 直接發請求:request.post(url,data=data,headers=xxxx) res = requests.post( url=self.url, data=data, headers=self.headers ) # html = res.text html = res.json() print(html) result = html['translateResult'][0][0]['tgt'] # 獲取相應請求 return result # 主函數 def main(self): # 輸入翻譯單詞 word = input('請輸入要翻譯的單詞') res = self.attack_yd(word) print("翻譯結果",res) if __name__ == '__main__': s = YdSpider() s.main()
1.目標
一、URL: http://www.mca.gov.cn/ - 民政數據 - 行政區劃代碼 即: http://www.mca.gov.cn/article/sj/xzqh/2019/
二、目標: 抓取最新中華人民共和國縣以上行政區劃代碼
2.實現步驟
1.從民政數據網站中提取最新行政區劃代碼連接
# 特色 1、最新的在上面 2、命名格式: 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,指向新的連接)
1、向二級頁面連接發請求獲得響應內容,並查看嵌入的JS代碼 2、正則提取真實的二級頁面連接 # 相關思路代碼 two_html = requests.get(two_link, headers=headers).text # 從二級頁面的響應中提取真實的連接(此處爲JS動態加載跳轉的地址) new_two_link = re.findall(r'window.location.href="(.*?)"', two_html, re.S)[0]
3.在數據庫中查詢此條連接是否已經爬取,創建增量爬蟲
1、數據庫中創建version表,存儲爬取的連接 2、每次執行程序和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 Govement(object): def __init__(self): self.one_url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/' self.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'} self.db = pymysql.connect('192.168.153.138','tiger','123456','govdb') self.cursor = self.db.cursor() # 獲取假連接 def get_flase_link(self): html = requests.get(self.one_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: title = a.get('title') # 正則匹配title中包含這個字符串的連接 if title.endswith('代碼'): # 獲取到第1個就中止便可,第1個永遠是最新的連接 false_link = 'http://www.mca.gov.cn' + a.get('href') break # 提取真連接 self.get_real_link(false_link) def get_real_link(self,false_link): # 從已提取的two_link中提取二級頁面的真實連接 two_html = requests.get(false_link, headers=self.headers).text # 從二級頁面的響應中提取真實的連接(此處爲JS動態加載跳轉的地址) real_two_link = re.findall(r'window.location.href="(.*?)"', two_html, re.S)[0] self.incre_spider(real_two_link) def incre_spider(self,real_two_link): # 實現增量爬取 self.cursor.execute('select * from version') result = self.cursor.fetchall() if result: if result[0][0] == real_two_link: print('已經是最新,無須爬取') else: self.get_data(real_two_link) self.cursor.execute('delete from version') self.cursor.execute('insert into version values(%s)',[real_two_link]) self.db.commit() # 用xpath直接提取數據 def get_data(self,real_two_link): real_two_html = requests.get(real_two_link,headers=self.headers).text parse_html = etree.HTML(real_two_html) # 基準xpath,提取每一個信息的節點列表對象 tr_list = parse_html.xpath('//tr[@height=19]') city_info = {} for tr in tr_list: city_info['code'] = tr.xpath('./td[2]/text()')[0] city_info['name'] = tr.xpath('./td[3]/text()')[0] print(city_info) if __name__ == '__main__': spider = Govement() spider.get_flase_link()
import requests from lxml import etree import re import pymysql class GovmentSpider(): def __init__(self): self.url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/' self.headers={'User-Agent':'Mozilla/5.0'} 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 #等於content.decode() #解析 parse_html = etree.HTML(html) print(parse_html) #網頁對象 a_list = parse_html.xpath('//a[@class="artitlelist"]') for a in a_list: #titel = a.xpath('./@titel')[0] #get()方法:獲取某個屬性的值 title = a.get('title') if title.endswith('代碼'):#末尾以代碼結束的 false_link = 'http://www.mca.gov.cn'+a.get('href') break # if false_link 在數據庫表中沒有: # self.get_true_link(false_link) # 把連接插入到數據庫中 # else: # print('數據已是最新,無需爬取') self.incr_spider(false_link) #增量爬取函數 def incr_spider(self, false_link): sel = 'select url from version ' self.cursor.execute(sel) # fetchall:(('http://xxx.html',),) result = self.cursor.fetchall() # not result:表明數據庫version表中無數據 if not result: self.get_true_link(false_link) #可選操做:數據庫version表中只保留最新一條數據 del_ = 'delete from version' self.cursor.execute(del_) # 把爬取後的url插入到version ins = 'insert into version values(%s)' self.cursor.execute(ins, [false_link]) self.db.commit() else: print('數據已是最新,無需爬取') #獲取真連接 def get_true_link(self,false_link): #先獲取加連接的響應,而後根據響應獲取真連接 html = requests.get( url=false_link, headers=self.headers ).text #利用正則提取真是連接 re_bds = r'window.location.href="(.*?)"' pattern = re.compile(re_bds,re.S) # 打印看看是否成功爬取頭 # print(html) # with open('false_link.html','a') as f: # f.write(html) true_link = pattern.findall(html)[0] self.save_data(true_link) # print(true_link) #提取數據 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=GovmentSpider() spider.main()