requests.post()

控制台抓包

打开方式几常用选项

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: 对响应内容进行预览
       3、Response:响应内容

requests.post()

1.适用场景

  Post类型请求的网站

2.参数-data

response = requests.post(url,data=data,headers=headers)
# data :post数据(Form表单数据-字典格式)

3.请求方式特点

GET请求 : 参数在URL地址中有显示
POST请求: Form表单提交数据

有道翻译破解案例(post)

1.目标

破解有道翻译接口,抓取翻译结果
# 结果展示
请输入要翻译的词语: elephant
翻译结果: 大象
**************************
请输入要翻译的词语: 喵喵叫
翻译结果: mews

2.实现步骤

1、浏览器F12开启网络抓包,Network-All,页面翻译单词后找Form表单数据
2、在页面中多翻译几个单词,观察Form表单数据变化(有数据是加密字符串)
3、刷新有道翻译页面,抓取并分析JS代码(本地JS加密)
4、找到JS加密算法,用Python按同样方式加密生成加密数据
5、将Form表单数据处理为字典,通过requests.post()的data参数发送

具体实现

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表单数据变化

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.目标

1、URL: http://www.mca.gov.cn/ - 民政数据 - 行政区划代码
   即: http://www.mca.gov.cn/article/sj/xzqh/2019/
2、目标: 抓取最新中华人民共和国县以上行政区划代码

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()
代码实现1
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()
代码实现2

 

posted @ 2019-08-13 21:23  maplethefox  阅读(1643)  评论(0编辑  收藏  举报