一、爬虫基本原理

一 爬虫是什么

#1、什么是互联网?
    互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样。

#2、互联网建立的目的?
    互联网的核心价值在于数据的共享/传递:数据是存放于一台台计算机上的,而将计算机互联到一起的目的就是为了能够方便彼此之间的数据共享/传递,否则你只能拿U盘去别人的计算机上拷贝数据了。

#3、什么是上网?爬虫要做的是什么?
    我们所谓的上网便是由用户端计算机发送请求给目标计算机,将目标计算机的数据下载到本地的过程。
    #3.1 只不过,用户获取网络数据的方式是:
      浏览器提交请求->下载网页代码->解析/渲染成页面。

    #3.2 而爬虫程序要做的就是:
      模拟浏览器发送请求->下载网页代码->只提取有用的数据->存放于数据库或文件中
 
    #3.1与3.2的区别在于:
      我们的爬虫程序只提取网页代码中对我们有用的数据

#4、总结爬虫
    #4.1 爬虫的比喻:
      如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的猎物/数据

    #4.2 爬虫的定义:
      向网站发起请求,获取资源后分析并提取有用数据的程序 

    #4.3 爬虫的价值:
      互联网中最有价值的便是数据,比如天猫商城的商品信息,链家网的租房信息,雪球网的证券投资信息等等,这些数据都代表了各个行业的真金白银,可以说,谁掌握了行业内的第一手数据,谁就成了整个行业的主宰,如果把整个互联网的数据比喻为一座宝藏,那我们的爬虫课程就是来教大家如何来高效地挖掘这些宝藏,掌握了爬虫技能,你就成了所有互联网信息公司幕后的老板,换言之,它们都在免费为你提供有价值的数据。

二 爬虫的基本流程

#1、发起请求
使用http库向目标站点发起请求,即发送一个Request
Request包含:请求头、请求体等

#2、获取响应内容
如果服务器能正常响应,则会得到一个Response
Response包含:html,json,图片,视频等

#3、解析内容
解析html数据:正则表达式,第三方解析库如Beautifulsoup,pyquery等
解析json数据:json模块
解析二进制数据:以b的方式写入文件

#4、保存数据
数据库
文件

三 请求与响应

#http协议:http://www.cnblogs.com/huchong/p/8288558.html

#Request:用户将自己的信息通过浏览器(socket client)发送给服务器(socket server)

#Response:服务器接收请求,分析用户发来的请求信息,然后返回数据(返回的数据中可能包含其他链接,如:图片,js,css等)

#ps:浏览器在接收Response后,会解析其内容来显示给用户,而爬虫程序在模拟浏览器发送请求然后接收Response后,是要提取其中的有用数据。

四 Request

#1、请求方式:
    常用的请求方式:GET,POST
    其他请求方式:HEAD,PUT,DELETE,OPTHONS

    ps:用浏览器演示get与post的区别,(用登录演示post)

    post与get请求最终都会拼接成这种形式:k1=xxx&k2=yyy&k3=zzz
    post请求的参数放在请求体内:
        可用浏览器查看,存放于form data内
    get请求的参数直接放在url后

#2、请求url
    url全称统一资源定位符,如一个网页文档,一张图片
    一个视频等都可以用url唯一来确定

    url编码
    https://www.baidu.com/s?wd=图片
    图片会被编码(看示例代码)


    网页的加载过程是:
    加载一个网页,通常都是先加载document文档,
    在解析document文档的时候,遇到链接,则针对超链接发起下载图片的请求

#3、请求头
    User-agent:请求头中如果没有user-agent客户端配置,
    服务端可能将你当做一个非法用户
    host
    cookies:cookie用来保存登录信息

    一般做爬虫都会加上请求头


#4、请求体
    如果是get方式,请求体没有内容
    如果是post方式,请求体是format data

    ps:
    1、登录窗口,文件上传等,信息都会被附加到请求体内
    2、登录,输入错误的用户名密码,然后提交,就可以看到post,正确登录后页面通常会跳转,无法捕捉到post 
from urllib.parse import urlencode
import requests

headers={
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Cookie':'H_WISE_SIDS=101556_115474_115442_114743_108373_100099_115725_106201_107320_115339_114797_115553_116093_115546_115625_115446_114329_115350_114275_116040_110085; PSTM=1494300712; BAIDUID=42FE2934E37AF7AD1FA31D8CC7006D45:FG=1; BIDUPSID=2996557DB2710279BD865C50F9A68615; MCITY=-%3A; __cfduid=da9f97dea6458ca26aa4278280752ebb01508939712; BDSFRCVID=PGLsJeCCxG3wt_3ZUrBLDfv2D_qBZSjAgcEe3J; H_BDCLCKID_SF=tJAOoCLytI03qn5zq4Oh-4oHhxoJq5QxbT7Z0l8KtfcNVJQs-lCMhbtp-l3GJPoLWK6hBKQmWIQHDnbsbq0M2tcQXR5-WROCte74KKJx-4PWeIJo5tKh04JbhUJiB5OLBan7Lq7xfDDbbDtmej_3-PC3ql6354Rj2C_X3b7EfKjIOtO_bfbT2MbyeqrNQlTkLIvXoITJQD_bEP3Fbfj2DPQ3KabZqjDjJbue_I05f-oqebT4btbMqRtthf5KeJ3KaKrKW5rJabC3hPJeKU6qLT5Xjh6B5qDfyDoAbKOt-IOjhb5hMpnx-p0njxQyaR3RL2Kj0p_EWpcxsCQqLUonDh8L3H7MJUntKjnRonTO5hvvhb6O3M7-XpOhDG0fJjtJJbksQJ5e24oqHP-kKPrV-4oH5MQy5toyHD7yWCvjWlT5OR5Jj6KMjMkb3xbz2fcpMIrjob8M5CQESInv3MA--fcLD2ch5-3eQgTI3fbIJJjWsq0x0-jle-bQypoa-U0j2COMahkMal7xO-QO05CaD53yDNDqtjn-5TIX_CjJbnA_Hn7zepoxebtpbt-qJJjzMerW_Mc8QUJBH4tR-T3keh-83xbnBT5KaKO2-RnPXbcWjt_lWh_bLf_kQN3TbxuO5bRiL66I0h6jDn3oyT3VXp0n54nTqjDHfRuDVItXf-L_qtDk-PnVeUP3DhbZKxtqtDKjXJ7X2fclHJ7z-R3IBPCD0tjk-6JnWncKaRcI3poiqKtmjJb6XJkl2HQ405OT-6-O0KJcbRodobAwhPJvyT8DXnO7-fRTfJuJ_DDMJDD3fP36q4QV-JIehmT22jnT32JeaJ5n0-nnhP3mBTbA3JDYX-Oh-jjRX56GhfO_0R3jsJKRy66jK4JKjHKet6vP; ispeed_lsm=0; H_PS_PSSID=1421_24558_21120_17001_24880_22072; BD_UPN=123253; H_PS_645EC=44be6I1wqYYVvyugm2gc3PK9PoSa26pxhzOVbeQrn2rRadHvKoI%2BCbN5K%2Bg; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598',
'Host':'www.baidu.com',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}

# response=requests.get('https://www.baidu.com/s?'+urlencode({'wd':'美女'}),headers=headers)
response=requests.get('https://www.baidu.com/s',params={'wd':'美女'},headers=headers) #params内部就是调用urlencode
print(response.text)

五 Response

#1、响应状态
    200:代表成功
    302:代表跳转
    404:文件不存在
    403:权限
    502:服务器错误

#2、Respone header
    set-cookie:可能有多个,是来告诉浏览器,把cookie保存下来
    
#3、preview就是网页源代码
    最主要的部分,包含了请求资源的内容
    如网页html,图片
    二进制数据等

六 总结

#1、总结爬虫流程:
    爬取--->解析--->存储

#2、爬虫所需工具:
    请求库:requests,selenium
    解析库:正则,beautifulsoup,pyquery
    存储库:文件,MySQL,Mongodb,Redis

#3、爬虫常用框架:
    scrapy
import requests
import re
import time
import hashlib

def get_page(url):
    print('GET %s' %url)
    try:
        response=requests.get(url)
        if response.status_code == 200:
            return response.content
    except Exception:
        pass

def parse_index(res):
    obj=re.compile('class="items.*?<a href="(.*?)"',re.S)
    detail_urls=obj.findall(res.decode('gbk'))
    for detail_url in detail_urls:
        if not detail_url.startswith('http'):
            detail_url='http://www.xiaohuar.com'+detail_url
        yield detail_url

def parse_detail(res):
    obj=re.compile('id="media".*?src="(.*?)"',re.S)
    res=obj.findall(res.decode('gbk'))
    if len(res) > 0:
        movie_url=res[0]
        return movie_url


def save(movie_url):
    response=requests.get(movie_url,stream=False)
    if response.status_code == 200:
        m=hashlib.md5()
        m.update(('%s%s.mp4' %(movie_url,time.time())).encode('utf-8'))
        filename=m.hexdigest()
        with open(r'./movies/%s.mp4' %filename,'wb') as f:
            f.write(response.content)
            f.flush()


def main():
    index_url='http://www.xiaohuar.com/list-3-{0}.html'
    for i in range(5):
        print('*'*50,i)
        #爬取主页面
        index_page=get_page(index_url.format(i,))
        #解析主页面,拿到视频所在的地址列表
        detail_urls=parse_index(index_page)
        #循环爬取视频页
        for detail_url in detail_urls:
            #爬取视频页
            detail_page=get_page(detail_url)
            #拿到视频的url
            movie_url=parse_detail(detail_page)
            if movie_url:
                #保存视频
                save(movie_url)


if __name__ == '__main__':
    main()


#并发爬取
from concurrent.futures import ThreadPoolExecutor
import queue
import requests
import re
import time
import hashlib
from threading import current_thread

p=ThreadPoolExecutor(50)

def get_page(url):
    print('%s GET %s' %(current_thread().getName(),url))
    try:
        response=requests.get(url)
        if response.status_code == 200:
            return response.content
    except Exception as e:
        print(e)

def parse_index(res):
    print('%s parse index ' %current_thread().getName())
    res=res.result()
    obj=re.compile('class="items.*?<a href="(.*?)"',re.S)
    detail_urls=obj.findall(res.decode('gbk'))
    for detail_url in detail_urls:
        if not detail_url.startswith('http'):
            detail_url='http://www.xiaohuar.com'+detail_url
        p.submit(get_page,detail_url).add_done_callback(parse_detail)

def parse_detail(res):
    print('%s parse detail ' %current_thread().getName())
    res=res.result()
    obj=re.compile('id="media".*?src="(.*?)"',re.S)
    res=obj.findall(res.decode('gbk'))
    if len(res) > 0:
        movie_url=res[0]
        print('MOVIE_URL: ',movie_url)
        with open('db.txt','a') as f:
            f.write('%s\n' %movie_url)
        # save(movie_url)
        p.submit(save,movie_url)
        print('%s下载任务已经提交' %movie_url)
def save(movie_url):
    print('%s SAVE: %s' %(current_thread().getName(),movie_url))
    try:
        response=requests.get(movie_url,stream=False)
        if response.status_code == 200:
            m=hashlib.md5()
            m.update(('%s%s.mp4' %(movie_url,time.time())).encode('utf-8'))
            filename=m.hexdigest()
            with open(r'./movies/%s.mp4' %filename,'wb') as f:
                f.write(response.content)
                f.flush()
    except Exception as e:
        print(e)

def main():
    index_url='http://www.xiaohuar.com/list-3-{0}.html'
    for i in range(5):
        p.submit(get_page,index_url.format(i,)).add_done_callback(parse_index)


if __name__ == '__main__':
    main()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Janti

记一次内存溢出的分析经历——thrift带给我的痛orz

说在前面的话 朋友,你经历过部署好的服务突然内存溢出吗? 你经历过没有看过Java虚拟机,来解决内存溢出的痛苦吗? 你经历过一个BUG,百思不得其解,头发一根一...

59280
来自专栏信安之路

Google Calaboratory 的另一个 XSS 漏洞

三个月以前,我写了一篇文章来介绍我在 Google Colaboratory 上发现的一个 XSS 漏洞,这篇文章是对前文的一些扩展,并且展示了我在同一个 we...

22040
来自专栏编程

新手学习python遇到的一些简单问题

1.python2 还是python3? 新手经常在这个问题上思考了很久,2和3的语法大致相同,改动不 大,如在python2中print xxx,...

19890
来自专栏技术记录

rabbitMQ教程(二)一篇文章看懂rabbitMQ

一、rabbitMQ是什么:   RabbitMQ,遵循AMQP协议,由内在高并发的erlanng语言开发,用在实时的对可靠性要求比较高的消息传递上。   学过...

36070
来自专栏JavaEdge

网站的伸缩性架构一、网站架构的伸缩性设计二、应用服务器集群的伸缩性设计三、分布式缓存集群的伸缩性设计四、数据存储服务器集群的伸缩性设计

44190
来自专栏Golang语言社区

PHP调用Go服务的正确方式 - Unix Domain Sockets

作者:枕边书 链接:http://www.cnblogs.com/zhenbianshu/p/7265415.html 來源:博客园 问题 可能是由于经验太少,...

49890
来自专栏pangguoming

ubuntu 64位android项目报错的解决方案,打开64位 Ubuntu 的32位支持功能

ubuntu的64位下的android环境,说实话,还真得费点精力了,解决一个问题,又出来一个新问题。 小编昨天刚好不容易将android的环境搭建好了,这不,...

30150
来自专栏安恒网络空间安全讲武堂

小丑—骚思路之一元购买国外服务器

1.5K40
来自专栏瓜大三哥

UVM(十二)之各register model

UVM(十二)之各register model 1. register model的必要性 考虑一个问题,当验证平台向DUT发了某些激励后,我们期望DUT中的某...

360100
来自专栏我和PYTHON有个约会

莱茨狗-Go语言第二弹:环境搭建

两种环境包,根据需要下载 如果你是windows江湖新手,那么下载msi安装包吧,界面图形化鼠标傻瓜式操作,全程安装辅助基本没有问题!

7910

扫码关注云+社区

领取腾讯云代金券