网络爬虫概述

网络爬虫概述

定义

网络蜘蛛、网络机器人,抓取网络数据的程序。

其实就是用Python程序模仿人点击浏览器并访问网站,而且模仿的越逼真越好。

爬取数据目的

1、获取大量数据,用来做数据分析
2、公司项目的测试数据,公司业务所需数据

企业获取数据方式

1、公司自有数据
2、第三方数据平台购买(数据堂、贵阳大数据交易所)
3、爬虫爬取数据

Python做爬虫优势

1、Python :请求模块、解析模块丰富成熟,强大的Scrapy网络爬虫框架
2、PHP :对多线程、异步支持不太好
3、JAVA:代码笨重,代码量大
4、C/C++:虽然效率高,但是代码成型慢

爬虫分类

1、通用网络爬虫(搜索引擎使用,遵守robots协议)
   robots协议 :网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取,
               通用网络爬虫需要遵守robots协议(君子协议)
              https://www.taobao.com/robots.txt
2、聚焦网络爬虫 :自己写的爬虫程序

爬虫爬取数据步骤

1、确定需要爬取的URL地址
2、由请求模块向URL地址发出请求,并得到网站的响应
3、从响应内容中提取所需数据
   1、所需数据,保存
   2、页面中有其他需要继续跟进的URL地址,继续第2步去发请求,如此循环

==爬虫请求模块一==

模块名及导入

1、模块名:urllib.request
2、导入方式:
   1、import urllib.request
   2、from urllib import request

常用方法详解

urllib.request.urlopen()方法

  • 作用

向网站发起请求并获取响应对象

  • 参数
1、URL:需要爬取的URL地址
2、timeout: 设置等待超时时间,指定时间内未得到响应抛出超时异常
  • 第一个爬虫程序

打开浏览器,输入百度地址(http://www.baidu.com/),得到百度的响应

response = urllib.request.urlopen('http://www.baidu.com/')
  • 响应对象(response)方法
1、bytes = response.read()
2、string = response.read().decode('utf-8')
# 返回实际数据的url地址(重定向问题)
3、url = response.geturl()
4、code = response.getcode()
# 补充
5、string.encode()
6、bytes.decode()

思考:网站如何来判定是人类正常访问还是爬虫程序访问???

# 向测试网站: http://httpbin.org/get 发请求,查看自己请求头
"headers": {
    "Accept-Encoding": "identity", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.6"
  }, 

urllib.request.Request()

作用

创建请求对象(包装请求,重构User-Agent,使程序更像正常人类请求)

参数

1、URL:请求的URL地址
2、headers:添加请求头(爬虫和反爬虫斗争的第一步)

使用流程

1、构造请求对象(重构User-Agent)
req = urllib.request.Request(
                            url='http://httpbin.org/get',
                             headers={'User-Agent':'...'})
2、发请求获取响应对象(urlopen)
res = urllib.request.urlopen(req)
3、获取响应对象内容
html=res.read().decode()

示例

向测试网站(http://httpbin.org/get)发起请求,构造请求头并从响应中确认请求头信息

from urllib import request

url = 'http://httpbin.org/get'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5'}
req = request.Request(url=url, headers=headers)
res = request.urlopen(req)
html = res.read().decode('utf-8')
print(html)

==URL地址编码模块==

模块名及导入

模块

# 模块名
urllib.parse
# 导入
import urllib.parse
from urllib import parse

作用

给URL地址中查询参数进行编码

编码前:https://www.baidu.com/s?wd=美女
编码后:https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3

常用方法

urlencode({dict})

URL地址中 ==一个== 查询参数

# 查询参数:{'wd' : '美女'}
# urlencode编码后:'wd=%e7%be%8e%e5%a5%b3'

# 示例代码
query_string = {'wd' : '美女'}
result = parse.urlencode(query_string)
# result: 'wd=%e7%be%8e%e5%a5%b3'

URL地址中 ==多个== 查询参数

from urllib import parse
query_string_dict = {
    'wd' : '美女',
    'pn' : '50'
}
query_string = parse.urlencode(query_string_dict)
url = 'http://www.baidu.com/s?{}'.format(query_string)
print(url)

拼接URL地址的3种方式

# url = 'http://www.baidu.com/s?'
#params='wd=%e....&pn=20'
1、字符串相加
相加  +
2、字符串格式化(占位符)
'...%s'% params
3、format()方法
# url = 'http://www.baidu.com/s?{}'
# params='wd=%e....&pn=20'
url = url.format(params)

练习
在百度中输入要搜索的内容,把响应内容保存到本地文件

from urllib import request
from urllib import parse


# 拼接URL地址
def get_url(word):
    url = 'http://www.baidu.com/s?{}'
    params = parse.urlencode({'wd': word})
    url = url.format(params)
    return url


# 发请求,保存
def request_url(url, filename):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5'}
    req = request.Request(url=url, headers=headers)
    res = request.urlopen(req)
    html = res.read().decode('utf-8')
    with open(filename, 'w',encoding='utf-8') as w:
        w.write(html)


if __name__ == '__main__':
    word = input('请输入搜索内容:')
    url = get_url(word)
    filename = word + '.html'
    request_url(url, filename)

quote(string)编码

示例1

from urllib import parse

string = '美女'
print(parse.quote(string))
# 结果: %E7%BE%8E%E5%A5%B3

改写之前urlencode()代码,使用quote()方法实现

from urllib import parse

url = 'http://www.baidu.com/s?wd={}'
word = input('请输入要搜索的内容:')
query_string = parse.quote(word)
print(url.format(query_string))

unquote(string)解码

示例

from urllib import parse

string = '%E7%BE%8E%E5%A5%B3'
result = parse.unquote(string)
print(result)

总结

  • urllib.request

    1. req =
    2. res =
    3. html=
  • res 方法

    1. res.read()
    2. res.getcode()
    3. res.geturl()
  • urllib.parse

    1. urllib.parse.urlencode()

案例

百度贴吧数据抓取
要求

1、输入贴吧名称  周杰伦吧
2、输入起始页
3、输入终止页
4、保存到本地文件:第1页.html、第2页.html ...

实现步骤

    1. 查看是否为静态页面

    右键 - 查看源代码 - 搜索关键字

    1. 找URL规律
第1页:http://tieba.baidu.com/f?kw=??&pn=0
第2页:http://tieba.baidu.com/f?kw=??&pn=50
第n页:http://tieba.baidu.com/f?kw=??&pn=(n-1)*50
    1. 获取网页内容

    2. 提取所需数据

    3. 保存(本地文件、数据库)

代码实现


正则解析模块re

re模块使用流程

  • 方法一
r_list=re.findall('正则表达式',html,re.S)
  • 方法二
# 1、创建正则编译对象
pattern = re.compile(r'正则表达式',re.S)
r_list = pattern.findall(html)

正则表达式元字符

元字符 含义
. 任意一个字符(不包括\n)
\d 一个数字
\s 空白字符
\S 非空白字符
[] 包含[]内容
* 出现0次或多次
+ 出现1次或多次

思考:请写出匹配任意一个字符的正则表达式?

import re
# 方法一
pattern=re.compile('.',re.S)
# 方法二
pattern=re.compile('[\s\S]')

贪婪匹配和非贪婪匹配

贪婪匹配(默认)

1、在整个表达式匹配成功的前提下,尽可能多的匹配 *
2、表示方式:.*    .+     .?

非贪婪匹配

1、在整个表达式匹配成功的前提下,尽可能少的匹配 *
2、表示方式:.*?    .+?     .??
import re

html = '''
<div><p>九霄龙吟惊天变</p></div>
<div><p>风云际汇潜水游</p></div>
'''
pattern = re.compile('<div><p>.*</p></div>', re.S)
pattern1 = re.compile('<div><p>.*?</p></div>', re.S)
pattern2 = re.compile('<div><p>(.*?)</p></div>', re.S)
r_list = pattern.findall(html)
r_list1 = pattern1.findall(html)
r_list2 = pattern2.findall(html)
print(r_list)
print(r_list1)
print(r_list2)
['<div><p>九霄龙吟惊天变</p></div>\n<div><p>风云际汇潜水游</p></div>']
['<div><p>九霄龙吟惊天变</p></div>', '<div><p>风云际汇潜水游</p></div>']
['九霄龙吟惊天变', '风云际汇潜水游']

正则表达式分组

作用

在完整的模式中定义子模式,将每个圆括号中子模式匹配出来的结果提取出来

示例

import re

s = 'A B C D'
p1 = re.compile('\w+\s+\w+')
print(p1.findall(s))
# 分析结果是什么???
# 结果:['A B','C D']

p2 = re.compile('(\w+)\s+\w+')
print(p2.findall(s))
# 分析结果是什么???
# 第一步: 把()去掉,先匹配完整['A B','C D']
# 第二步: 提取分组()中内容['A','C']

p3 = re.compile('(\w+)\s+(\w+)')
print(p3.findall(s))
# 分析结果是什么???
# 第一步: 把()去掉,先匹配完整['A B','C D']
# 第二步: 提取分组()中内容[('A','B'),('C','D')]

分组总结

1、在网页中,想要什么内容,就加()
2、先按整体正则匹配,然后再提取分组()中的内容
   如果有2个及以上分组(),则结果中以元组形式显示 [(),(),()]

练习

页面结构如下:

<div class="animal">
    <p class="name">
        <a title="Tiger"></a>
    </p>
    <p class="content">
        Two tigers two tigers run fast
    </p>
</div>

<div class="animal">
    <p class="name">
        <a title="Rabbit"></a>
    </p>

    <p class="content">
        Small white rabbit white and white
    </p>
</div>

从以上html代码结构中完成如下内容信息的提取:

问题1 :[('Tiger',' Two...'),('Rabbit','Small..')]
问题2 :
    动物名称 :Tiger
    动物描述 :Two tigers two tigers run fast
    **********************************************
    动物名称 :Rabbit
    动物描述 :Small white rabbit white and white

今日作业

1、把百度贴吧案例重写一遍,不要参照课上代码
2、爬取猫眼电影信息 :猫眼电影-榜单-top100榜

第1步完成:
    猫眼电影-第1页.html
    猫眼电影-第2页.html
    ... ... 

第2步完成:
    1、提取数据 :电影名称、主演、上映时间
    2、先打印输出,然后再写入到本地文件

3、复习任务

pymysql、MySQL基本命令  
MySQL :建库建表普通查询等

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

推荐阅读更多精彩内容