首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫之链式调用、beautifulsoup、IP代理池、验证码破解

爬虫之链式调用、beautifulsoup、IP代理池、验证码破解

作者头像
GH
发布2020-03-19 15:43:41
1.4K0
发布2020-03-19 15:43:41
举报

目录

  • 一、链式调用
  • 二、beautifulsoup
    • 2.1介绍
    • 2.2 基本使用
    • 2.3遍历文档树
    • 2.4 搜索文档树
    • 2.5修改文档树
    • 2.6总结
    • 2.7实例:爬取小说三国演义
    • 2.8实例:爬取盗墓笔记
  • 三、ip代理池(收费代理、免费代理)
    • 3.1收费代理池
    • 3.2免费代理池
  • 四、验证码破解(打码平台)
    • 4.1用python如何调用dll文件

一、链式调用

在python中实现链式调用只需在函数返回对象自己就行了。

 1 class Person:
 2     def name(self, name):
 3         self.name = name
 4         return self
 5 
 6     def age(self, age):
 7         self.age = age
 8         return self
 9 
10     def show(self):
11         print "My name is", self.name, "and I am", self.age, "years old."
12 
13 p = Person()
14 p.name("Li Lei").age(15).show()

二、beautifulsoup

2.1介绍

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.你可能在寻找 Beautiful Soup3 的文档,Beautiful Soup 3 目前已经停止开发,官网推荐在现在的项目中使用Beautiful Soup 4, 移植到BS4

#安装 Beautiful Soup
pip install beautifulsoup4

#安装解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .根据操作系统不同,可以选择下列方法来安装lxml:

$ apt-get install Python-lxml

$ easy_install lxml

$ pip install lxml

另一个可供选择的解析器是纯Python实现的 html5lib , html5lib的解析方式与浏览器相同,可以选择下列方法来安装html5lib:

$ apt-get install Python-html5lib

$ easy_install html5lib

$ pip install html5lib

下表列出了主要的解析器,以及它们的优缺点,官网推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定.

解析器

使用方法

优势

劣势

Python标准库

BeautifulSoup(markup, "html.parser")

Python的内置标准库执行速度适中文档容错能力强

Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差

lxml HTML 解析器

BeautifulSoup(markup, "lxml")

速度快文档容错能力强

需要安装C语言库

lxml XML 解析器

BeautifulSoup(markup, ["lxml", "xml"])``BeautifulSoup(markup, "xml")

速度快唯一支持XML的解析器

需要安装C语言库

html5lib

BeautifulSoup(markup, "html5lib")

最好的容错性以浏览器的方式解析文档生成HTML5格式的文档

速度慢不依赖外部扩展

中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html

2.2 基本使用

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

#基本使用:容错处理,文档的容错能力指的是在html代码不完整的情况下,使用该模块可以识别该错误。使用BeautifulSoup解析上述代码,能够得到一个 BeautifulSoup 的对象,并能按照标准的缩进格式的结构输出
from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,'lxml') #具有容错功能
res=soup.prettify() #处理好缩进,结构化显示
print(res)

2.3遍历文档树

每一个BeautifulSoup 的对象的标签都可以看成一个个对象,标签的属性可以看成对象的属性,通过遍历、查找文档树查找到的标签依然可以看成一个对象。

#遍历文档树:即直接通过标签名字选择,特点是选择速度快,但如果存在多个相同的标签则只返回第一个
#1、用法
#2、获取标签的名称
#3、获取标签的属性
#4、获取标签的内容

# 必须掌握的
head=soup.head
print(head)
p=soup.p
print(p)
p=soup.body.p
print(p)

# 获取p标签的名字
p=soup.body.p
print(p.name)

# 获取属性
# 当你获取class的时候,获取的是个列表?class可以有多个
p=soup.body.p
print(p['class'])
print(p['id'])
print(p.attrs.get('class'))此方法与上面的方法相同

# 获取内容
# text:获取所有的文字,包括子标签(笔记多),爬去文章时可以直接获取文章内容div的text就能取出文章内的所有文字
# string:获取当前第一级目录的文字,如果嵌套多层,就取不出文字
# strings:生成器,每一层的文字都放在里面
p=soup.body.p
print(p.text)
print(p.string)
print(list(p.strings))

# 用的比较少(了解)
#5、嵌套选择
print(soup.head.title.string)
print(soup.body.a.string)

#6、子节点、子孙节点
print(soup.body.p.contents)
print(list(soup.body.p.children))
print(list(soup.body.p.descendants)) #子子孙孙

#7、父节点、祖先节点
print(soup.body.p.parent)  #直接父节点
print(list(soup.body.p.parents)) # 父亲,父亲的父亲。。。全都放到生成器中

#8、兄弟节点
print(soup.a.next_sibling) #下一个兄弟
print(soup.a.previous_sibling) #上一个兄弟

2.4 搜索文档树

Beautiful Soup定义了很多搜索方法,这里着重介绍2个:find()find_all() 。其它方法的参数和用法类似,请读者举一反三。

find_all( name , attrs , recursive , text , **kwargs )、find( name , attrs , recursive , text , **kwargs )

find_all找出所有满足条件的标签,如果有多个就放在列表中;find找出满足条件的第一个标签,就算有多个也只找第一个,具体使用方法如下:

# p是标签对象,跟soup是一样的
# p=soup.find(name='p',class_='story')
# print(p)
# b=soup.find(name='b')
# print(b)

# 通过属性查找方式一
# b=soup.find(id='id_b')
# print(b)

# 通过属性查找的方式二
# b=soup.find(attrs={'id':'id_b'})
# p=soup.find(attrs={'class':'story'})
# print(p)

# 列表查找
# ret=soup.find_all(name=['p','b'])
# ret=soup.find_all(id=['id_b','link1'])
# print(ret)

# 正则
# import re
# # 查找名字以b开头的标签
# # ret=soup.find_all(name=re.compile('^b'))
# ret=soup.find_all(id=re.compile('^l'))
# print(ret)

# True
# 查找所有有id的标签
# ret=soup.find_all(id=True)
# ret=soup.find_all(name=True)
# print(ret)

# 方法
# def has_class_but_no_id(tag):
#     return tag.has_attr('class') and not tag.has_attr('id')
# ret=soup.find_all(has_class_but_no_id)
# print(ret)

# 取属性,取文字
# tag对象['src']   tag对象.attrs.get('src')
# tag对象.text   string

# 遍历文档树和搜索文档树可以同时用
# soup.body.find(name='p').b
# soup.body.find(name='p').find()
# print(type(soup))

# #Tag对象用起来跟BeautifulSoup对象用起来完全一样
# body=soup.body
# print(type(body))

# 拓展 链式调用(跟语言没关系,jq)
# 链式调用在python中如何实现?点多少次,其实还是对象本身
# class A:
#     def test(self,name):
#         self.name=name
#         return self
#     def test2(self,age):
#         self.age=age
#         return self

# a=A()
# a.test('lqz').test2(19)
# print(a.age)


# bs4 其他用法
#limit 限制查找的个数
# ret=soup.find_all(name='p',limit=1)
# print(ret)
# soup.find_all()

# recursive 是否递归查找
# ret=soup.body.find_all(name='p',recursive=False)
# ret2=soup.body.find_all(name='p',recursive=True)
# print(len(ret))
# print(len(ret2))

2.5修改文档树

Beautiful Soup的强项是文档树的搜索,但同时也可以方便的修改文档树,具体使用方法参见Beautiful Soup 4.2.0 文档

链接:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#id40

2.6总结

# 总结:
#1、推荐使用lxml解析库
#2、三种选择器:标签选择器,find与find_all,css选择器
    1、标签选择器筛选功能弱,但是速度快
    2、建议使用find,find_all查询匹配单个结果或者多个结果
    3、如果对css选择器非常熟悉建议使用select
#3、记住常用的获取属性attrs和文本值get_text()的方法

2.7实例:爬取小说三国演义

import requests,re,os
from bs4 import BeautifulSoup

ret = requests.get('http://www.shicimingju.com/book/sanguoyanyi.html')
# print(ret.text)
soup = BeautifulSoup(ret.text,'lxml')
mulu_li = soup.find(name='div',class_='book-mulu')
# print(mulu_li)
ret1 = soup.select('.book-mulu>ul>li')
#http://www.shicimingju.com/book/sanguoyanyi/1.html
content_str = ''
if not os.path.isdir('三国演义'):
    os.mkdir('三国演义')

#分章节下载
for i in ret1:
    # print(i.text)
    name = i.text
    url = 'http://www.shicimingju.com' + i.find(name='a')['href']
    # print(url)
    ret2 = requests.get(url)
    soup = BeautifulSoup(ret2.text, 'lxml')
    div = soup.find(name='div', class_="card bookmark-list")
    content = div.text
    head = div.find(name='h1').text
    with open(f'三国演义/{head}.md','wt',encoding='utf-8') as f:
        f.write(content)
        
#统一下载到一个文件
# for i in ret1:
#     # print(i.text)
#     name = i.text
#     url = 'http://www.shicimingju.com' + i.find(name='a')['href']
#     # print(url)
#     ret2 = requests.get(url)
#     soup = BeautifulSoup(ret2.text, 'lxml')
#     div = soup.find(name='div', class_="card bookmark-list")
#     content_str += div.text
# with open('三国演义/三国演义.md','wt',encoding='utf-8') as f:
#       f.write(content_str)
#       f.flush()
#       print('下载完成')
# print(content_str)
    # head = div.find(name='h1').text
    # with open(f'三国演义/{head}.md','wt',encoding='utf-8') as f:
    #     f.write(content)

    # print(content)

2.8实例:爬取盗墓笔记

#爬盗墓笔记
ret = requests.get('http://www.dmbj.cc/')
ret.encoding = 'utf-8'
# print(ret.text)
soup = BeautifulSoup(ret.text,'lxml')
li_list = soup.find_all(name='li',class_='pop-book')

for i in li_list:

    book_name1 = i.text.strip()
    # print(book_name1)
    book_name = book_name1.strip('\n南派三叔')
    print(book_name)
    book_url = i.find(name='a')['href']
    ret2 = requests.get(book_url)
    ret2.encoding = 'utf-8'
    soup2 = BeautifulSoup(ret2.text, 'lxml')
    # print(ret2)
    content_div = soup2.find(name='div',class_="xsbox clearfix")
    url = content_div.find_all(name='a')
    if not os.path.isdir(f'{book_name}'):
        os.mkdir(f'{book_name}')
    # print(content_div)

    for j in url:
        # print(j.text)
        content_url = j['href']
        content_name = j.text
        if content_name[-1] == '?':
            content_name = content_name.strip('?')
        ret3 = requests.get(content_url)
        ret3.encoding = 'utf-8'
        soup3 = BeautifulSoup(ret3.text, 'lxml')
        content = soup3.find(name='div',class_="m-post").text

        with open(f'{book_name}/{content_name}.txt', 'wt', encoding='utf-8') as f:

            f.write(content)
        # print(content)

三、ip代理池(收费代理、免费代理)

ip代理池就是一个存放有很多ip的数据库,当我们请求这个数据库接口时可以得到一个由接口随机返回的ip和端口,我们可以使用这些ip作为我们的ip去向某个网站发送请求,这样可以防止服务端因为我们请求次数过多而封我们的ip。

#代理的使用方法,proxies内是我们的代理ip
ret=requests.get('http://101.133.225.166:8088/',
                 proxies={'http':'222.95.241.88:3000'}
 )

在访问某些需要校验cookie的服务端时,只有IP代理池还不够,我们需要做一个cookie池,每次向服务器发送请求时的ip和cookie都是随机组合的,这样服务端就会以为这些请求是不同的用户发出的,从而使我们在爬虫的时候不会被封ip。

3.1收费代理池

收费代理池一般是第三方做的ip代理网站,如:http://www.goubanjia.com/

3.2免费代理池

我们可以从网上爬取一些免费的代理ip自己做代理池,步骤:自己搭建:flask框架搭建服务,后台用爬虫(requests爬取免费),放入redis。

当然,我们还可以使用GitHub上开源的个人代理池项目,这时别人写好的项目,我们只需要部署到自己的服务器上就可以使用。自己爬的代理ip需要我们定时对这些ip进行测试,保证ip是可用的,测试方式:用这些ip向某个网站发送请求,如果有响应就可以使用。

#1  下载下来,打开
#2 安装依赖  pip3 install -r requirements.txt
#3 修改配置文件Config/setting.py
35行左右,意思是爬取的代理放到redis中,
DB_TYPE = getenv('db_type', 'redis').upper()
DB_HOST = getenv('db_host', '127.0.0.1')
DB_PORT = getenv('db_port', 6379)
DB_PASSWORD = getenv('db_password', '')
#4  跑项目 可以在cli目录下通过ProxyPool.py启
python3 proxyPool.py schedule:爬取代理
python3 proxyPool.py webserver:启动服务
#5 测试
http://127.0.0.1:5010/get/ 发一次,取一个代理ip

四、验证码破解(打码平台)

这里需要用到第三方的打码平台,从网上的验证码图片,传给它,他就给你识别,(12306的验证码,模拟登陆12306)。

我们还可以使用一些程序去识别一些图片,但是一般识别率比较低。

4.1用python如何调用dll文件

python调用dll详解参考链接https://www.cnblogs.com/blog-rui/p/11662827.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、链式调用
  • 二、beautifulsoup
    • 2.1介绍
      • 2.2 基本使用
        • 2.3遍历文档树
          • 2.4 搜索文档树
            • 2.5修改文档树
              • 2.6总结
                • 2.7实例:爬取小说三国演义
                  • 2.8实例:爬取盗墓笔记
                  • 三、ip代理池(收费代理、免费代理)
                    • 3.1收费代理池
                      • 3.2免费代理池
                      • 四、验证码破解(打码平台)
                        • 4.1用python如何调用dll文件
                        相关产品与服务
                        验证码
                        腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档