爬虫-案例

前提:爬虫的实际例子

  搜索引擎(百度、谷歌、360搜索等)。
         伯乐在线。
         惠惠购物助手。
        数据分析与研究(数据冰山知乎专栏)。
        抢票软件等。

 

为什么用Python写爬虫程序:

PHP:PHP是世界是最好的语言,但他天生不是做这个的,而且对多线程、异步支持不是很好,并发处理能力弱。爬虫是工具性程序,对速度和效率要求比较高。

Java:生态圈很完善,是Python爬虫最大的竞争对手。但是Java语言本身很笨重,代码量很大。重构成本比较高,任何修改会导致代码大量改动。爬虫经常要修改采集代码。

C/C++:运行效率是无敌的。但是学习和开发成本高。写个小爬虫程序可能要大半天时间。

Python:语法优美、代码简洁、开发效率高、支持的模块多。相关的HTTP请求模块和HTML解析模块非常丰富。还有Scrapy和Scrapy-redis框架让我们开发爬虫变得异常简单。

1、爬虫是啥?

   通俗理解:爬虫是一个模拟人类请求网站行为的程序。可以自动请求网页、并数据抓取下来,然后使用一定的规则提取有价值的数据。

2、http协议里需要关注的

2.1 请求需要关注的东西 requests

url : 告诉浏览器,你要去哪里

Method:

get:

数据:url?key=value&key=value

post:

请求体:

form data

文件类型

json

headers:

cookie:保存用户登录状态

User-Agent:告诉服务器你是谁

refere:告诉服务器你从哪里来

服务器规定的特殊字段

 

2.2 请求需要关注的东西 response

Status Code:

2xx

请求成功(不一定)---后台程序员自己规定的---不能用作请求成功的唯一判断标准

3xx

重定向

响应头:

location:重定向地址

set_cookie:设置cookie

服务器规定的特殊字段

 

响应体:

1.html代码(css,html,js)

2.json

3.二进制(图片,视频,音频)

 

 

3、 常用请求库、解析库、数据库的用法

3.1 常用请求库 测试网站:http://httpbin.org/get

request库

安装:pip install requests

使用

请求

①get请求:

                响应对象 = requests.get(......)

**参数:**

url:

headers = {}

cookies = {}       优先级低于headers里的cookie字段

params = {}

proxies = {'http':‘http://ip:端口’}

timeout = 0.5

allow_redirects = True

 

②post请求:

                响应对象 = requests.post(......)

**参数:**

url:

headers = {}

cookies = {}

data = {}

json = {}

files = {‘file’:open(...,‘rb’)}

timeout = 0.5

allow_redirects = False

自动保存cookie的请求:

            session = requests.session()

r = session.get(......)

r = session.post(......)
补充:(保存cookie到本地)
import http.cookiejar as cookielib
session.cookie = cookielib.LWPCookieJar()
session.cookie.save(filename='1.txt')

session.cookies.load(filename='1.txt')

响应:

            r.url

r.text   常用

r.encoding = 'gbk'   常用

r.content     常用

r.json()     常用

r.status_code   用的少

r.headers  

r.cookies  

r.history  

 

3.2 常用解析语法

css选择器

1、类选择器

.类名

2、id选择器

#id值

3、标签选择器

标签名

4、后代选择器

选择器1 选择器2

5、子选择器

选择器1>选择器2

6、属性选择器

[属性名] #只要有这个属性名的,都会被选中

[属性名 = 属性值] #只要有这个属性名,并且值相等的,都会被选中

<h1 class="xxx yyy " ></h1>

[class="xxx yyy "]

[属性名 ^= 值]

[属性名 &= 值]

[属性名*= 值]

 

7、群组选择器

选择器1,选择器2 or

8、多条件选择器

选择器1选择器2 and

p[pro="xxx"]

 

xpath选择器

 

3.3 牛逼的requests-html

安装: pip install requests-html

使用:

请求:

            from requests_html import HTMLSession

session = HTMLSession()

**参数:**

browser.args = [

'--no-sand',

'--user-agent=XXXXX'

]

响应对象 = session.request(......)

响应对象 = session.get(......)

响应对象 = session.post(......)

参数和requests模块一毛一样

响应:

            r.url

**属性和requests模块一毛一样

**

解析:

html对象属性:

            r.html.absolute_links          /xx/yy   -->    http://www....../xx/yy

  .links                 路径原样

          .base_url         网站基础路径

          .html             解码过的响应内容   #相当于r.text

          .text

          .encoding = 'gbk'     控制的是r.html.html的解码格式  

          .raw_html           相当于r.content

          .pq

html对象方法:

            r.html.find('css选择器')              [element对象,element对象...]

  .find('css选择器',first = True)     对一个element对象

  .xpath(‘xpath选择器’)

  .xpath('‘xpath选择器',first = True)

  .search(‘模板’)                 result对象(匹配第一次)

          (‘xxx{}yyy{}’)[0]

  (‘xxx{name}yyy{pwd}’)[‘name’]

  .search_all('模板')             匹配所有,[result对象,result对象,....]

  .render(.....)               渲染后的结果去替换 r.html.html

  **参数:**

  script:“”“ ( ) => {

js代码

js代码

}

”“”

  scrolldown:n

  sleep:n

  keep_page:True/False


绕过网站对webdriver的检测:
'''
() =>{
                              Object.defineProperties(navigator,{
                              webdriver:{
                                  get: () => undefined
                                  }
                              })
                          }
                          '''

Element对象方法及属性

        element对象 .absolute_links
  .links
  .text
  .html
  .attrs
  .find('css选择器')
  .search('模板')
  .search_all('模板')

与浏览器交互 r.html.page.XXX

                async def xxx():

await r.html.page.XXX

session.loop.run....(xxx())


.screenshot({'path':路径,'clip':{'x':1,'y':1,'width':100,'height':100}})

.evaluate('''() =>{js代码}’‘’})

.cookies()

.type('css选择器',’内容‘,{’delay‘:100})

.click('css选择器',{'button':'left','clickCount':1,'delay':0})

.focus('css选择器')

.hover('css选择器')

.waitForSelector('css选择器')

.waitFor(1000)

键盘事件 r.html.page.keyboard.XXX

            .down('Shift')

.up('Shift')

.press('ArrowLeft')

.type('喜欢你啊',{‘delay’:100})

鼠标事件 r.html.page.mouse.XXX

 

            .click(x,y,{
              'button':'left',
              'click':1
              'delay':0
})
.down({'button':'left'})
.up({'button':'left'})
.move(x,y,{'steps':1})

.

常用数据库

###mongoDB4.0:

下载:https://www.mongodb.com/

安装:略

注意:使用前修改bin目录下配置文件mongodb.cfg,删除最后一行的'mp'字段

####1. 启动服务与终止服务

net start mongodb

net stop mongodb

2.创建管理员用户

mongo

use admin

db.createUser({user:"yxp",pwd:"997997",roles:["root"]})

3.使用账户密码连接mongodb

mongo -u adminUserName -p userPassword

4.数据库

查看数据库
show dbs
切换数据库
use db_name
增加数据库
db.table1.insert({'a':1})  创建数据库(切换到数据库插入表及数据)
删除数据库
db.dropDatabase()  删数据库(删前要切换)

5.表

使用前先切换数据库
查看表
show tables 查所有的表
增加表
db.table1.insert({'b':2})  增加表(表不存在就创建)
删除表
db.table1.drop()    删表

数据

增加数据

db.test.insert(user0)    插入一条
db.user.insertMany([user1,user2,user3,user4,user5])   插入多条

删除数据

db.user.deleteOne({ 'age': 8 })   删第一个匹配
db.user.deleteMany( {'addr.country': 'China'} ) 删全部匹配
db.user.deleteMany({}) 删所有

查看数据

db.user.find({'name':'alex'})   查xx==xx
db.user.find({'name':{"$ne":'alex'}})   查xx!=xx
db.user.find({'_id':{'$gt':2}})   查xx>xx
db.user.find({"_id":{"$gte":2,}}) 查xx>=xx
db.user.find({'_id':{'$lt':3}}) 查xx<xx
db.user.find({"_id":{"$lte":2}}) 查xx<=xx

改数据

db.user.update({'_id':2},{"$set":{"name":"WXX",}})   改数据

pymongo

conn = pymongo.MongoClient(host=host,port=port, username=username, password=password)
db = client["db_name"] 切换数据库
table = db['表名']
table.insert({}) 插入数据
table.remove({})   删除数据
table.update({'_id':2},{"$set":{"name":"WXX",}})   改数据
table.find({}) 查数据

 

爬虫与反爬虫的对抗历史

1565136366701

 

 

常见反扒手段

1.检测浏览器headers

2.ip封禁

3.图片验证码

4.滑动模块

5.js加密算法

5.js轨迹

6.前端反调试

 

小爬爬

1.爬校花图片(模仿校花的都得死)

2.爬豆瓣电影

3.校花电影m3u8(凉凉夜色)

4.爬取天猫

反爬虫:使用技术手段防止爬虫程序的方法

误伤:反扒技术将普通用户识别为爬虫,如果误伤过高,效果再好也不能用

成本:反爬虫需要的人力和机器成本

拦截:成功拦截爬虫,一般情况下,拦截率越高,误伤率越高

 

5.分析腾讯视频url

接口:https://p2p.1616jx.com/api/api.php?url=vip视频地址

mitmproxy基本用法:
class XXX():
    def request(self,flow:mitmproxy.http.HTTPFlow):
        捕获请求
     def response(self,flow: mitmproxy.http.HTTPFlow):
        捕获响应
​
addons = [
    Vip_film()
]   
        
flow.request.headers ---- 获取请求头
flow.request.url ---- 获取请求url
flow.response.get_text() ---- 获取响应体
flow.response.set_text() ---- 设置响应体

 


运行:mitmdump -s 脚本.py
播放器:
<script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.1.js" charset="utf-8"></script>;
       <div class="mod_player" id="mod_player" r-notemplate="true"></div>
给播放器传值:
var player =  new TcPlayer('mod_player', {
               "m3u8":m3u8播放地址,
               "autoplay" : true,      //iOS 下 safari 浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的
               "width" :  '100%%',//视频的显示宽度,请尽量使用视频分辨率宽度
               "height" : '100%%'//视频的显示高度,请尽量使用视频分辨率高度
          })

 

6.登录知乎

保存cookie到本地

jsdom使用:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
window = dom.window;
document = window.document;
XMLHttpRequest = window.XMLHttpRequest;

 

7.红薯小说(js注入)

script='''
var span_list = document.getElementsByTagName("span")
for (var i=0;i<span_list.length;i++){
    var content = window.getComputedStyle(
        span_list[i], ':before'
    ).getPropertyValue('content');
    span_list[i].innerText = content.replace('"',"").replace('"',"");
}
''' 

8、爬取天猫数据

  问题:为什么访问天猫商品第一页数据时不需要登录,当选择下一页时就自动跳到登录页面?是什么机制实现这个原理的?

 

 

 

 

 

 当访问第二页时自动跳转到登录的界面,检测cookie需要登录才能访问数据。关键字段s=60和sort=&,控制着登录,这是一个漏洞。

 

 问题的关键切入点是分析第一页和第二页的url字段,有哪些不同。

第一页的url:

 

 第二页的url:

 必须手动选择跳过的页面,获取来获取url

 

 点击确定,请求获取url:

 

 

得出结论:当把关键字段sort删除时,就不需要登录校验可以任意跳转到其他页面。

删除多余的字段信息进行访问也不需要登录直接跳转成功,并返回数据:

 

 通过分析跳过登录,直接访问第八页的数据:

 

代码的实现原理:

  get访问该url,去掉多余的字段,写个while循环,写个package页面的范围进行爬取商品数据信息,加入数据库MongoDB保存请求的数据信息,为了防止IP过度请求被封,在GitHub上调取代理池的接口。

 

 

 

 

 

 

 

 































 

posted @ 2019-12-17 23:05  游走De提莫  阅读(368)  评论(0编辑  收藏  举报