爬虫知识库

参考视频:2022年最新Python爬虫零基础教程

常用库:

  • urllib.request -- 请求网页数据的模块,但被 requests 模块代替了
  • requests -- 十分好用的请求网页数据的模块
  • re -- 正则表达式模块
  • bs4 -- 网页信息提取模块
  • xpath -- 在 XML / HTML 中查找信息的模块
  • pyquery -- 更加灵活的处理网页信息(可以修改网页信息)
  • Thread -- 多线程
  • ThreadPoolExecutor -- 线程池
  • Process -- 多进程
  • ProcessPoolExecutor -- 进程池
  • asyncio -- 协程
  • aiohttp -- 异步 http 请求库
  • aiofiles -- 异步文件操作库
  • selenium -- 自动化测试模块,模拟真人打开浏览器,主要是用来解决 JS 渲染的问题
  • AJAX -- 动态页面数据抓取

库用法:

① requests

import requests

url = "xxx"
# GET
resp = requests.get(url, params=params)
print(resp.text) # 打印响应文
# POST
resp = requests.post(url, data=data)
print(resp.json()) # 返回 json 格式响应文时使用

# 部分参数
params = {
    'wd': '中国'
}
data = {
    'first': 'true',
    'pn': '1',
    'kd': 'Python'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'
}

# 部分用法
resp.url                       # 返回 url 地址
resp.encoding                  # 返回响应头部字符编码,准确性较低,省时
resp.apparent_encoding         # 返回响应头部字符编码,准确性较高,耗时
resp.status_code               # 返回响应码,200 为正常

type(resp.text)                # str 类型
type(resp.content)             # byte 类型
resp.text                      # 根据 resp.encoding 自动转换网页内容,准确性较低
resp.content                   # 显示网页原内容,即 byte 类型网页内容
resp.content.decode('utf-8')   # 显示 str 类型网页内容

# Session 会话用法
session = requests.session()

# 模拟用户登入,一般步骤如下
1. session.post(URL1, data=data)        # 模拟登入
2. print(resp.cookies)                  # 查看 Cookie
3. resp = session.get(URL2)             # 访问目标网站
4. print(resp.text)                     # 查看访问内容

3. headers = {'Cookie': 'xxx'}          # 也可以先在 URL1 网站存储 Cookie
4. resp = requests.get(URL2, headers=headers)  # 直接访问目标网站


# Json 格式处理
# 此处省略获取 json 格式的请求,如 Video_Json = requests.get(VideoUrl, headers=headers).json()
Video_Json =
{
  "resultCode": "1",
  "resultMsg": "success",
  "reqId": "30df5a33-a18a-492d-a8bd-22230ff9d7a0",
  "systemTime": "1657678924851",
  "videoInfo": {
    "playSta": "1",
    "video_image": "https://xxx.com/cont/xxx.png",
    "videos": {
      "hdUrl": "",
      "hdflvUrl": "",
      "sdUrl": "",
      "sdflvUrl": "",
      "srcUrl": "https://xxx.com/mp4/xxx.mp4"
    }
  }
}

# 获取 json 目标值
Target = Video_Json ['videoInfo']['videos']['srcUrl']
# https://xxx.com/mp4/xxx.mp4


# 下载图片格式 / 视频格式
PicUrl = xxx.png
with open("temp.jpg", mode="wb") as f:
        f.write(requests.get(PicUrl).content)

VideoUrl = xxx.mp4
with open("temp.mp4", mode="wb") as f:
    f.write(requests.get(VideoUrl).content)

② re

import re

# 基础用法
result = re.findall(r"\d+", "123我是筱团465啦啦啦789")
print(result)
# ['123', '465', '789']

# 迭代器,常用用法
result = re.finditer(r"\d+", "123我是筱团465啦啦啦789")
for item in result:
    print(item.group())
# 123
# 465
# 789

# 只搜索第一个匹配项
result = re.search(r"\d+", "123我是筱团465啦啦啦789")
print(result.group())
# 123

# 只匹配从头开始能完全匹配的一个匹配项
result = re.match(r"\d+", "123我是筱团465啦啦啦789")
print(result.group())
# 123

# 预加载
obj = re.compile(r"\d+")
for i in data:
    result = obj.finditer(content)

# 实操
# 想要提取数据必须用小括号括起来,可以单独起名字
# (?P<名字>正则表达式)
# 提取数据的时候,需要 group("名字")
data = """
<div class='西游记'><span id='10010'>中国联通</span></div>
<div class='西游记'><span id='10086'>中国移动</span></div>
"""
obj = re.compile(r"<span id='(?P<id>\d+)'>(?P<name>.*?)</span>")
result = obj.finditer(data)
for item in result:
    id = item.group("id")
    print(id)
    name = item.group("name")
    print(name)
# 10010
# 中国联通
# 10086
# 中国移动

③ bs4

from bs4 import BeautifulSoup

html = """
<ul>
    <li><a href="zhangwuji.com">张无忌</a></li>
    <li id="abc"><a href="zhouxingchi.com">周星驰</a></li>
    <li><a href="zhubajie.com">猪八戒</a></li>
    <li><a href="wuzetian.com">武则天</a></li>
    <a href="jinmaoshiwang.com">金毛狮王</a>
</ul>
"""

page = BeautifulSoup(html, "html.parser")

# page.find("标签名", attrs={"属性": "值"}) # 查找某个元素, 只会找到一个结果
li = page.find("li", attrs={"id": "abc"})

# page.find_all("标签名", attrs={"属性": "值"}) # 查找到全部结果
li = page.find_all("li", attrs={"id": "abc"})
# 还可以通过 CSS 选择器进行查找,用法为 page.select(xxx)

# 继续查找标签中的内容
a = li.find("a")

# 获取文本
print(a.text)
# 获取属性
print(a.get("href"))

# 实操
li_list = page.find_all("li")
for li in li_list:
    a = li.find("a")
    text = a.text
    href = a.get("href")
    print(text, href)
"""
张无忌 zhangwuji.com
周星驰 zhouxingchi.com
猪八戒 zhubajie.com
武则天 wuzetian.com
"""

④ xpath

from lxml import etree

xml = """
<book>
    <id>1</id>
    <name>野花遍地香</name>
    <price>1.23</price>
    <nick>臭豆腐</nick>
    <author>
        <nick id="10086">周大强</nick>
        <nick id="10010">周芷若</nick>
        <nick class="jay">周杰伦</nick>
        <nick class="jolin">蔡依林</nick>
        <div>
            <nick>惹了</nick>
        </div>
    </author>
    <partner>
        <nick id="ppc">胖胖陈</nick>
        <nick id="ppbc">胖胖不陈</nick>
    </partner>
</book>
"""

# 处理 XML
et = etree.XML(xml)

# / 表示根节点
result = et.xpath("/book")

# 在 xpath 中间的 / 表示的是儿子
result = et.xpath("/book/name")

# text() 拿文本
result = et.xpath("/book/name/text()")[0]
# 野花遍地香

# // 表示的是子孙后代.
result = et.xpath("/book//nick")

# * 表示通配符
result = et.xpath("/book/*/nick/text()")
# ['周大强', '周芷若', '周杰伦', '蔡依林', '胖胖陈', '胖胖不陈']

# [] 表示属性筛选 [@属性名=值]
result = et.xpath("/book/author/nick[@class='jay']/text()")
# ['周杰伦']

# 最后一个 / 表示拿到 nick 里面的 id 的内容,@属性 可以直接拿到属性值
result = et.xpath("/book/partner/nick/@id")
# ['ppc', 'ppbc']


html = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
</head>
<body>
    <ul>
        <li><a href="http://www.baidu.com">百度</a></li>
        <li><a href="http://www.google.com">谷歌</a></li>
        <li><a href="http://www.sogou.com">搜狗</a></li>
    </ul>
    <ol>
        <li><a href="feiji">飞机</a></li>
        <li><a href="dapao">大炮</a></li>
        <li><a href="huoche">火车</a></li>
    </ol>
    <div class="job">李嘉诚</div>
    <div class="common">胡辣汤</div>
</body>
</html>
"""

# 处理 HTML
et = etree.HTML(html)

# 与处理 XML 类似,获取特定的文本内容
li = et.xpath("/html/body/ul/li[2]/a/text()")
# ['谷歌']

# // 表示直接选取目标属性
li_list = et.xpath("//li")
for li in li_list:
    # ./ 表示当前节点
    href = li.xpath("./a/@href")[0]
    text = li.xpath("./a/text()")[0]
    print(text, href)
"""
百度 http://www.baidu.com
谷歌 http://www.google.com
搜狗 http://www.sogou.com
飞机 feiji
大炮 dapao
火车 huoche
"""

⑤ pyquery

from pyquery import PyQuery

html = """
<ul>
    <li class="aaa"><a href="http://www.google.com">谷歌</a></li>
    <li class="aaa"><a href="http://www.baidu.com">百度</a></li>
    <li class="bbb" id="qq"><a href="http://www.qq.com">腾讯</a></li>
    <li class="bbb"><a href="http://www.yuanlai.com">猿来</a></li>
</ul>
"""

# 加载 html 内容
p = PyQuery(html)

# 打印 p 的内容
print(p)
"""
<ul>
    <li class="aaa"><a href="http://www.google.com">谷歌</a></li>
    <li class="aaa"><a href="http://www.baidu.com">百度</a></li>
    <li class="bbb" id="qq"><a href="http://www.qq.com">腾讯</a></li>
    <li class="bbb"><a href="http://www.yuanlai.com">猿来</a></li>
</ul>
"""

# 打印 p 的类型
print(type(p))
# <class 'pyquery.pyquery.PyQuery'>

# 选取目标标签,pyquery 对象直接(css 选择器)
a = p("a")
print(a)
# <a href="http://www.google.com">谷歌</a><a href="http://www.baidu.com">百度</a><a href="http://www.qq.com">腾讯</a><a href="http://www.yuanlai.com">猿来</a>

# 打印 a 的类型,依然是 pyquery 对象
print(type(a))
# <class 'pyquery.pyquery.PyQuery'>

# 链式操作
a = p("li")("a")
print(a)
# <a href="http://www.google.com">谷歌</a><a href="http://www.baidu.com">百度</a><a href="http://www.qq.com">腾讯</a><a href="http://www.yuanlai.com">猿来</a>

# 打印二层标签
a = p("li a")
print(a)
# <a href="http://www.google.com">谷歌</a><a href="http://www.baidu.com">百度</a><a href="http://www.qq.com">腾讯</a><a href="http://www.yuanlai.com">猿来</a>

# 打印类为 aaa 的标签(class="aaa"),二层标签为 a 的值
a = p(".aaa a")
print(a)
# <a href="http://www.google.com">谷歌</a><a href="http://www.baidu.com">百度</a>

# 打印 id 为 qq 的标签(id="qq"),二层标签为 a 的值
a = p("#qq a")
print(a)
# <a href="http://www.qq.com">腾讯</a>

# 打印 id 为 qq 的标签(id="qq"),二层标签为 a 的属性
href = p("#qq a").attr("href")
print(href)
# http://www.qq.com

# 打印 id 为 qq 的标签(id="qq"),二层标签为 a 的文本
text = p("#qq a").text()
print(text)
# 腾讯

# 如果多个标签同时拿属性 [attr]. 只能默认拿到第一个
href = p("li a").attr("href")
print(href)
# http://www.google.com

# 多个标签拿属性
it = p("li a").items()
for item in it:  # 从迭代器中拿到每一个标签
    href = item.attr("href")  # 拿到 href 属性
    text = item.text()
    print(text, href)
"""
谷歌 http://www.google.com
百度 http://www.baidu.com
腾讯 http://www.qq.com
猿来 http://www.yuanlai.com
"""

'''
快速总结:
1. pyquery(选择器)
2. items()       当选择器选择的内容很多的时候. 需要一个一个处理的时候
3. attr(属性名)   获取属性信息
4. text()        获取文本
'''


html = """
<div><span>我爱你</span></div>
"""

p = PyQuery(html)

html = p("div").html()  # 全都要
text = p("div").text()  # 只要文本, 所有的 html 标签被过滤掉
print(html)
print(text)
"""
<span>我爱你</span>
我爱你
"""


html = """
<HTML>
    <div class="aaa">哒哒哒</div>
    <div class="bbb">嘟嘟嘟</div>
</HTML>
"""

p = PyQuery(html)

# 在 xxx 标签后面添加 xxx 新标签
p("div.aaa").after("""<div class="ccc">吼吼吼</div>\n""")
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒</div>
    <div class="ccc">吼吼吼</div>
    <div class="bbb">嘟嘟嘟</div>
</HTML>
"""

# 在 xxx 标签中间添加 xxx 新标签
p("div.aaa").append("""<span>我爱你</span>""")
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒<span>我爱你</span></div>
    <div class="ccc">吼吼吼</div>
    <div class="bbb">嘟嘟嘟</div>
</HTML>
"""

# 修改属性
p("div.bbb").attr("class", "ddd")
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒<span>我爱你</span></div>
    <div class="ccc">吼吼吼</div>
    <div class="ddd">嘟嘟嘟</div>
</HTML>
"""

# 新增属性,前提是该标签没有这个属性
p("div.ddd").attr("id", "123456")
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒<span>我爱你</span></div>
    <div class="ccc">吼吼吼</div>
    <div class="ddd" id="123456">嘟嘟嘟</div>
</HTML>
"""

# 删除属性
p("div.ddd").remove_attr("id")  
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒<span>我爱你</span></div>
    <div class="ccc">吼吼吼</div>
    <div class="ddd">嘟嘟嘟</div>
</HTML>
"""

# 删除标签
p("div.ddd").remove()
print(p)
"""
<HTML>
    <div class="aaa">哒哒哒<span>我爱你</span></div>
    <div class="ccc">吼吼吼</div>
</HTML>
"""

# 小总结:p 可以直接修改 html 的内容,且可以永久修改

⑥ Thread,ThreadPoolExecutor,Process
⑦ asyncio,aiohttp,aiofiles
详情参考: python 高级用法 -- 进程、线程和协程

⑧ selenium
Chrome 内核下载

from selenium.webdriver import Chrome
from selenium.webdriver.support import expected_conditions as EC # 等待操作需要导入的库
from selenium.webdriver.common.action_chains import ActionChains # 用于完成一系列操作
from selenium.webdriver.support.wait import WebDriverWait # 等待某个特定的操作
from selenium.webdriver.chrome.options import Options # 设置参数
from selenium.webdriver.support.select import Select # 专门用于处理下拉框
from selenium.webdriver.common.keys import Keys # 所有按键的指令
from selenium.webdriver.common.by import By # 指定搜索方法

"""
两个前置条件:
1. 部分代码仅适用于 Chrome 内核
2. Chrome 驱动器需放置在 Python 编译器同目录下
"""

# 内核驱动参数
options = Options()
# 处理 SSL 证书错误问题、隐藏自动化操作、忽略无用的日志、禁用 GPU(默认添加)
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
options.add_argument('--disable-gpu')
# 使用代理,防止被 gank
options.add_argument('--proxy-server=http://120.220.220.95:8085')
# 无头浏览器,窗口调大,防止样式堆叠
options.add_argument("--headless")
options.add_argument("--window-size=4000,1600")

# 初始化
web = Chrome(options=options)
# 进入网站
web.get("http://www.baidu.com")
# 全局隐式等待 5 秒,即获取元素的函数超过 5 秒就报错超时
web.implicitly_wait(5)

# 窗口最大化
web.maximize_window()
# 切换到最新窗口(最旧窗口是 [0] / 最新窗口是 [-1])
web.switch_to.window(web.window_handles[-1])
# 关闭当前窗口
web.close()
# 切换到 iframe 中
web.switch_to.frame(iframe)
# 切换到上层 iframe
web.switch_to.parent_frame()
# 关闭整个驱动
web.quit()
# 获取窗口标题
title = web.title
# 获取目标元素(By.XPATH / By.CSS_SELECTOR / By.CLASS_NAME / By.ID)
element = web.find_element(By.XPATH, "//div[@class='job']/li")
elements = web.find_elements(By.CSS_SELECTOR, "div > button[type='submit']")
# 获取目标元素,若超过 10 秒就报错超时(不同于全局隐式等待,仅作用于特定函数)
elements = WebDriverWait(web, 10, 0.5).until(EC.presence_of_element_located((By.XPATH, "//div[@class='job']/li")))
# 获取元素文本内容
text = element.text
# 获取元素属性(@)
href = element.get_attribute("class")
href = element.get_property("href")
# 获取 cookies 列表,需要手动转换为字典
cookies = web.get_cookies()
# 元素框输入内容(Keys.ENTER / Keys.TAB / Keys.SPACE / Keys.BACK_SPACE)(仅使用于 input 标签)
element.send_keys("python") # send_keys("python", Keys.ENTER)
# 点击元素
element.click()
# 获取选择框元素(仅使用于 select 标签)
select = Select(element)
for option in select.options: # 列出全部选项
    select.select_by_visible_text(option.text) # 通过文字切换到目标选项
# 截图,获得图片字节(仅使用于 img 标签)
bs = img.screenshot_as_png
# 存储图片至文件中(适合存储 png 文件)
img.screenshot("pic.png")
# 事件链,用于连续完成一系列事件(最后一定要执行 perform 函数)
ActionChains(web).click_and_hold(button).move_by_offset(0, 300).perform()


"""
# 可以用如下代码获取 cookies 字典
cookies = web.get_cookies()
_cookies = {}
for cookie in cookies:
    _cookies[cookie['name']] = cookie['value']
cookies = _cookies
"""

正则表达式用法:

正则表达式在线测试

常用元字符:具有固定含义的特殊符号

.    匹配除换行符以外的任意字符,未来在python的re模块中是一个坑
\w   匹配字母或数字或下划线
\s   匹配任意的空白符
\d   匹配数字
\n   匹配一个换行符
\t   匹配一个制表符
^    匹配字符串的开始
$    匹配字符串的结尾
\W   匹配非字母或数字或下划线
\D   匹配非数字
\S   匹配非空白符
a|b  匹配字符 a 或字符 b
()   匹配括号内的表达式,也表示一个组
[...]  匹配字符组中的字符
[^...] 匹配除了字符组中字符的所有字符

量词:控制前面的元字符出现的次数

*    重复零次或更多次
+    重复一次或更多次
?    重复零次或一次
{n}  重复 n 次
{n,}  重复 n 次或更多次  PS: {0,} 相当于 * / {1,} 相当于 +
{n,m} 重复 n 到 m 次

贪婪匹配和惰性匹配

.*   贪婪匹配,尽可能多的去匹配结果
.*?  惰性匹配,尽可能少的去匹配结果 --> 回溯

HTML 基础语法规则:

1. <标签名 属性="值">被标记的内容</标签名>
2. <标签名 属性="值" />
3. <!-- 注释内容 -->
4. 实例如下
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>我是标题</title>
</head>

<body bgcolor="pink">
    <h1 align="right">我爱周润发</h1>
    <p>周润发同志. 曾经是一个赌神. 我特别崇拜他</p>
    <a href="http://www.baidu.com">周润发的个人主页</a>
    <img src="abc.jpg" width="50px" height="60px" />
</body>

</html>

XML 基础语法规则:

XML 和 HTML 的区别:
1. HTML 中的标记是用来显示数据的,而 XML 中的标记用来描述数据的性质和结构
2. HTML 是不区分大小写的,而 XML 是严格区分大小写的
3. HTML 可以有多个根元素,而格式良好的 XML 有且只能有一个根元素
4. HTML 中,内容中的空格是自动过滤的,而 XML 中,空格则不会自动删除
5. 实例如下
<book>
    <id>1</id>
    <name>野花遍地香</name>
    <price>1.23</price>
    <nick>臭豆腐</nick>
    <author>
        <nick id="10086">周大强</nick>
        <nick id="10010">周芷若</nick>
        <nick class="jay">周杰伦</nick>
        <nick class="jolin">蔡依林</nick>
        <div>
            <nick>惹了</nick>
        </div>
    </author>
    <partner>
        <nick id="ppc">胖胖陈</nick>
        <nick id="ppbc">胖胖不陈</nick>
    </partner>
</book>

CSS 基础语法规则:

1. 通过 style 属性来编写样式
<div style="width:100px;height:100px;border: 1px solid red;">你好, 我叫周润发</div>
2. 通过 style 标签. 然后使⽤选择器的形式来编写样式
<head>
    <style>
        span {
            color: pink;
        }
    </style>
</head>
3. 在 css ⽂件中编写样式, 通过 link 引⼊该⽂件
<head>
    <link rel="stylesheet" href="mycss.css">
</head>

CSS 选择器:

1. id 选择器          #
2. 标签选择器         标签
3. 类选择器           .
4. 选择器分组         ,
5. 后代选择器         空格
6. 子选择器           >
7. 相邻选择器         +
8. 属性选择器         [属性=值]

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #abc {
            color: pink;
        }
        li {
            border: 1px solid red;
        }
        .jay {
            color: green;
        }
        div, span {
            background: hotpink;
        }
        ul li {
            /* 空格表示子子孙孙, 所有后代 */
            list-style: none;
        }
        ul>li {
            /* > 表示儿子一层 */
            list-style: none;
        }
        h1+h2 {
            color: red;
        }
        a[target] {
            color: green;
        }
        a[target='_blank'] {
            text-decoration: none;
        }
    </style>
</head>

<body>
    <!--
    <ul>
        <li>周润发</li>
        <li id="abc">黎明</li>
        <li>周星驰</li>
        <li>
            <ol>
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
            </ol>
        </li>
    </ul>
    <ol>
        <li>手电筒</li>
        <li>电视机</li>
        <li>黑板擦</li>
    </ol>
    <div class="jay">呵呵哒</div>
    <span class="jay">呵呵哒</span>

    <h1>我爱麻花藤</h1>
    <h2>我爱黎明</h2>
    <h2>我也爱黎明</h2>
    -->
    <a href="#" target="_blank">我是blank</a>
    <a href="#" target="_self">我是self</a>
    <a href="#">我是啥也没有</a>
</body>

</html>

IP 代理池:

代理网站:快代理(用于测试的免费代理

# 使用单个代理
proxy = {
    "http": "http://182.84.144.66:3256/"
    # "https": "https://182.84.144.66:3256/"
}
resp = requests.get(URL, proxies=proxy)

# 使用代理池(快代理为例)
def get_ip():
    # 反复提取代理 ip
    while 1:
        # 快代理的 ip 池
        url = "https://ent.kdlapi.com/api/getproxy/xxx"
        resp = requests.get(url)
        ips = resp.json()
        if ips['code'] == 0:
            for ip in ips['data']['proxy_list']:  # 拿到每一个 ip
                print("正在使用的代理ip:", ip)
                yield ip  # 一个一个返回代理 ip
            print("所有 ip 已经用完, 即将更新!")  # for 循环结束,继续提取新 ip
        else:
            print("获取代理 ip 出现异常,重新获取!")

def spider():
    URL = "https://www.xxx.com"
    while 1:
        try:
            proxy_ip = next(gen)  # 拿到代理 ip
            # 不清楚为什么,加上 https 的代理似乎用不了
            # proxies = {"http": proxy_ip, "https": proxy_ip}
            proxies = {"http": proxy_ip}
            # print(proxies)
            # 设置 20 秒超时
            resp = requests.get(URL, proxies=proxies, timeout=20)
            # xxxxx
            # xxxxx
            return None # 运行成功后,强制返回
        except:
            print("报错了")

if __name__ == '__main__':
    gen = get_ip()  # 代理 ip 的生成器
    spider()

图形验证码识别:

图形验证码识别网站 1:超级鹰

#! /usr/bin/env python
# -*- coding: UTF-8 -*-

import requests
from hashlib import md5

class Chaojiying_Client(object):
    """
    超级鹰自带的类,调用即可
    """
    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def PostPic_base64(self, base64_str, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
            'file_base64':base64_str
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()

if __name__ == '__main__':
    chaojiying = Chaojiying_Client('137270xxxxx', 'LLxxxxx', '939271') # 用户名 / 密码 / 软件ID
    img_path = open('a.jpg', 'rb').read() # 读取本地图片
    result = chaojiying.PostPic(img_path, 1004) # 验证码类型,详情见超级鹰价格体系
    '''
    img = web.find_element(By.XPATH, '//div/img') # 读取网络图片,标签为 img
    bs = img.screenshot_as_png # 截图,获得图片字节
    result = chaojiying.PostPic(bs, 1004)
    '''
    code = result['pic_str'] # 识别结果
    print(result) # 打印结果

图形验证码识别网站 2:图鉴(推荐)

#! /usr/bin/env python
# -*- coding: UTF-8 -*-

import base64
import json
import requests

def base64_api(uname, pwd, img, typeid):
    """
    图鉴自带的类,调用即可
    """
    if(type(img) == type("str")): # 传入图片路径
        with open(img, 'rb') as f:
            base64_data = base64.b64encode(f.read())
            b64 = base64_data.decode()
    else: # 传入图片字节
        base64_data = base64.b64encode(img)
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]

if __name__ == "__main__":
    img_path = "pic.png" # 读取本地图片
    result = base64_api(uname='tuanzi', pwd='LLxxxxx', img=img_path, typeid=3) # 用户名 / 密码 / 图片类型
    '''
    img = web.find_element(By.XPATH, '//div/img') # 读取网络图片,标签为 img
    bs = img.screenshot_as_png # 截图,获得图片字节
    result = base64_api(uname='tuanzi', pwd='LLxxxxx', img=bs, typeid=3)
    '''
    print(result) # 打印结果

爬虫思路:

# 有条有理有步骤
def spider():
    url = "xxx"
    resp = requests.get(url, proxies=proxy, timeout=20)
    resp.encoding = "utf-8"
    return resp.text

# 使用 Postman 测试抓单个包是否能正常响应

# 分析网站的源代码(存储本地)
f = open("./reference.html", mode="w", encoding='utf-8')
resp = requests.get('https://www.xxx.com')
resp.encoding = 'utf-8'
f.write(resp.text)
f.close()

# 分析网站的源代码(本地分析)
f = open("./reference.html", mode="r", encoding='utf-8')
data = f.read()
f.close()

有用的网站:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容