1. 爬虫

[TOC]


1.1. 主要技术

基础技术栈 : requests + beautifulsoup + re

高级技术栈: scrapy框架

1.2. 爬虫基础知识

graph LR; start[开始链接] -->A[下载页面] A --1--> B[提取页面中的数据] A --2--> C[提取页面中的链接] C --3--> A B --> output[输出或存储]

AJAX:Asynchronous JavaScript And XML。异步的javascript和xml,可以在不刷新网页的情况下更新网页的数据。

Cookies:也称为Cookie,是网站用于辨别用户身份、进行session跟踪而存储在用户本地终端上的数据。Cookie最典型的应用是判断用户是否已经登录网站、保留用户信息以简化登录手续。

request携带的是"Cookie",response携带的是"Set-Cookie"。

如果响应头的状态码为30?,代表重定向。浏览器会根据响应头中的Location字段,再次发送GET请求。

JSON:JavaScript Object Notation,是一种轻量级的数据交换格式,是一种格式化字符串。

json与python的list或dict相互转换:

import json

# json -> list/dict
json.loads('{"a":"123"}')

# list/dict -> json
json.dumps({'a':123}, indent=4) # indent添加缩进,使显示更美观

XHR:XMLHttpReques,Ajax相关的一个重要对象。

https中用到的算法:

  • 非对称加密算法:RSA、DSA/DSS
  • 对称加密算法:AES、RC4、3DES
  • Hash算法:MD5、SHA1、SHA256

robots.txt:Robots Exclusion Standard,网络爬虫排除标准,网站告知网络爬虫哪些页面可以抓取,哪些不行。放在网站根目录下。

Cookie不能添加到请求头Headers中,不然只能在几个页面中得到数据,不是真正的登陆。

每个domain最多只有20条cookie,且每个cookie长度不超过4kB,否则会被截断。

数据来源:大部分数据来源于Doc、XHR、JS标签。

Requests的GET和POST方法的请求参数分别是params和data。

如果解码出错,可以使用errors选项忽略掉:

# xx是一个bytes
xx.decode(encoding=response.encoding, errors='ignore')

不分析url,直接爬取手机上的数据:使用UiAutomator操作Android手机(需要安装Android SDK、JRE),然后使用python来操作UI Automator,从而控制手机。将手机上的内容转换成xml形式,然后进行抓取。

模拟人操作手机屏幕的任何行为,并直接读取屏幕上的文字。

需要安装第三方库:

pip install uiautomator

注:UI Automator Viewer与python uiautomator 不能同时使用。

1.3. 反爬虫技术及应对手段

  1. 用户请求的Headers:对Headers的User-Agent进行检测,或者对Referer进行检测(一些资源网站的防盗链就是检测Referer)
  2. 用户操作网络行为:通过检测用户行为来判断用户行为是否合规。
    1. 同一IP短时间多次访问同一页面:使用IP代理,可以在IP代理平台上通过API接口获得,每请求几次就更换一个IP。
    2. 同一账户短时间内多次进行相同操作:每次请求间隔几秒后再发送下一个请求,可以在代码中加一个延时功能。
  3. 网站目录数据加载方式(采用异步加载):针对Ajax请求,分析具体的请求参数和响应的数据结构及其含义,在爬虫中直接模拟Ajax请求。
  4. 数据加密:某些网站可能对Ajax的请求参数进行加密
    1. 加密代码一般是使用javascript实现的,可以自行分析加密方式。
    2. 使用Selenium+chromedriver(自动化测试技术),调用浏览器内核,利用Selenium模拟人为操作网页,并触发网页中的js脚本。
    3. 验证码识别:通过第三方平台处理,或OCR技术识别。

1.4. 动态网页爬取

主要内容:抓取动态网页,执行相关的javascript代码,使用鼠标进行点击等

技术选择:

  • selenium:适合用来加载动态页面,进行比较复杂的登陆操作(各种类型的验证码)。
  • splash:用于加载动态页面(执行js)。

1.4.1. selenium:模拟浏览器

selenium是一个网页自动化测试工具,可以通过代码来操作网页上的各个元素。

python使用:

pip install selenium

下载浏览器驱动程序:

PhantomJS是没有无界面的,其他的2个有界面(也可以使用headless参数屏蔽页面)。

注:驱动要和本机上装的相应浏览器的版本保持一致,不然会出错。

chromedriver/firfoxdriver

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions

 chrome = webdriver.Chrome(executable_path=chrome_path)  # chrome_path指定驱动路径
 chrome.get(login_url)
 WebDriverWait(chrome, 5).until(
 expected_conditions.title_is('登录 - 新浪微博'), '加载登陆页面失败'
 )

? scrapy程序采用中间件MobilesDownloaderMiddleware实现Chrome浏览器的嵌入,当一个Request申请时,如果不是图片申请就使用Chrome浏览器获取网页的Response,以保证js的执行。否则直接使用默认方法得到response。

1.4.2. Splash:爬取动态页面

splash文档:https://splash.readthedocs.io/en/latest/index.html

github地址:https://github.com/scrapy-plugins/scrapy-splash

splash是一个JavaScript渲染引擎。使用WebKit开发的轻量级无界面浏览器,提供基于HTTP接口的JavaScript渲染服务。

splash安装

在linux上,使用docker运行splash:

docker pull scrapinghub/splash
docker run -p 8050:8050 -p 5023:5023 scrapinghub/splash

docker run -p 8050:8050 scrapinghub/splash

使用requests进行测试:

import requests
from scrapy.selector import Selector

host = 1.1.1.1 # 你docker(或splash)的安装地址
splash_url = 'http://' + host +' :8050/render.html'
args = {'url':'http://quotes.toscrape.com/js','timeout':10,'image':0}

response = requests.get(splash_url,params = args)  
sel = Selector(response)
sel.css('div.quote span.text::text').extract()

最后输出不为空,则说明安装成功。

splash服务:

  • render.html:提供JavaScript页面渲染服务。
  • execute:执行用户自定义的渲染脚本(lua),利用该端点可以在页面中执行JavaScript代码。

render.html

服务端点 render.html
请求地址 http://localhost:8050/render.html
请求方式 GET/POST
返回类型 html

常用参数:

args = {
    'url':'http://quotes.toscrape.com/js', # 需要渲染的js页面,必选
    'timeout':10,                           # 渲染页面超时时间,float
    'wait':2,                               # 等待页面渲染的时间,float
    'proxy':'http://u:passwd@host:port',   # 代理服务器地址
    'image':0,                               # 0为不下载图片,1为下载图片(默认)
    'js_source':'',                           # 用户自定义的js代码,在页面渲染前执行
}

execute端点

可以将execute端点的服务看做一个可用lua语言编程的浏览器,功能类似PhantomJS。使用lua脚本来模拟浏览器行为。

服务端点 execute
请求地址 http://localhost:8050/execute
请求方式 POST
返回类型 自定义

常用参数:

args = {
    'lua_source':'xxxx',                   # 用户自定义的lua脚本,必选
    'timeout':10,                           # 渲染页面超时时间,float
    'proxy':'http://u:passwd@host:port',   # 代理服务器地址
}

lua脚本必须包含一个main函数作为程序入口,main函数会传入一个splash对象(lua中的对象),用户可以调用该对象的方法来操作splash。

lua函数:

function main(splash)
    splash:go("http://example.com")                    -- 打开页面
    splash:wait(0.5)                                -- 等待加载
    local title = splash:evaljs("document.title")    -- 执行js代码
    return {title=title}                            -- 返回lua中的表,会被编码成json串。
end

常用函数:

  • splash:url():返回当前页面的url。
  • splash:html():返回当前页面的html文本。
  • splash:get_cookies():获取全部Cookie信息。

在scrapy中使用splash

首先需要安装scrapy-splash:

pip install scrapy-splash

相关配置:

# setting.py

SPLASH_URL = 'http://127.0.0.1:8050/'

# 开启下载中间件,并调整HttpCompressionMiddleware的次序
DOWNLOADER_MIDDLEWARES = {
    # Engine side
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
    # Downloader side
}

# 去重过滤器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

# 支持cache_args(可选)
SPIDER_MIDDLEWARES = {
    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

在scrapy_splash中有一个SplashRequest类,用户只需使用SplashRequst来替代Request发送请求。

在爬虫中调用:

from scrapy_splash import SplashRequst
yield SplashRequest(url,self.parse,endpoint='render.html',
                    args={}
                   )

1.5. 模拟登陆

1.5.1. 添加cookies

1. 从浏览器中复制请求头

在登陆某网站后,复制该页面的Request中Headers的Cookie。将其添加到请求头中。

有一种方法,直接copy请求头,然后将其附着到session上,这样只能访问你copy的那个网页,cookies并不会真正的被设置。

2. 使用browser_cookie3从浏览器中获得cookie

python库browser_cookie3可以获取chrome或firefox浏览器中的Cookie。

import browser_cookie3

# 返回http.cookiejar.CookieJar
browser_cookie3.chrome(domain_name=domain)

获取一个已经登录网站的cookie:

import requests
import browser_cookie3

# 返回一个 requests.cookies.RequestsCookieJar
def get_cookiejar_from_browser(domain):
    cj = browser_cookie3.chrome(domain_name=domain) 
    cookiejar = requests.cookies.RequestsCookieJar()
    for c in cj:
        cookiejar.set(c.name, c.value, domain=c.domain, path=c.path)
    return cookiejar

1.5.2. 模拟表单登陆

适合没有或只有简单验证手段的网站。如简单的数字验证码,可以调用ocr模块进行识别。

表单中可能会有隐藏项。

可以安装loginform来快速构建表单数据。

from loginform import fill_login_form

formdata, login_url, method = fill_login_form(login_url, response.text, user, passwd)

fill_login_form 返回包含3个元素的元组,分别是所有表单项组成的列表(每隔表单项是一个(x,y)类型的元组),登陆提交表单的地址,提交表单的方法。

OCR识别验证码

使用orc识别验证码,需要现在对应电脑上安装orc软件。

from PIL import Image # PIL通过pip install pillow安装
import pytesseract
from io import BytesIO

img = Image.open('code.png')
# img = Image.open(BytesIO(response.body))  # 使用ByteIO(bytes)转换

img = img.convert('L')            # 转换为黑白图
res = pytesseract.image_to_string(img)
img.close()

网络平台识别验证码

可以在阿里云市场找到验证码识别平台。购买,调用相关接口,获取识别结果。

人工识别验证码

将验证码图片显示出来,然后人工输入验证码。

1.5.3. 使用selenium模拟登陆

适用于验证码比较复杂的。

Copyright @appwhy all right reserved,powered by Gitbook文件更新于: 2020-06-17 09:37:25

results matching ""

    No results matching ""