python爬虫

python爬虫

一、爬虫基本概念:

​ 1、爬虫法律问题
​ 2、爬虫定义
​ 3、通用爬虫和聚焦爬虫的区别与联系
​ 4、url的搜索策略(基于ip地址搜索,广度优先,深度优先,最佳优先)

二、网页的基础知识:

​ 1、url的概念
​ 2、http和https
​ 3、http的请求过程
​ 4、请求,四部分内容:
​ 5、响应,三部分内容:
​ 6、网页构成:

三、爬虫基本的原理:

​ 1、获取网页的源代码(通过请求库发起http请求)

​ 2、提取信息(分析网页源代码,提取数据)
​ 3、保存数据(本地,数据库)

四、爬取技巧

​ 1、爬取多页:
​ 2、动态渲染页面的爬取:

五、反爬虫:

1.使用user-agent模拟浏览器,header加入
2.多账号登录:加入cookies,cookies池
3.代理:突破ip的限制,ip池,requests.get(url,proxies=proxies,timeout=10)
4.验证码OCR识别,机器学习方法,接入打码平台
5.使用selenium完全模拟浏览器
6.抓包软件分析

一、爬虫基本概念:

1、爬虫法律问题

​ 从目前的实践来看,如果抓取数据的行为用于个人使用,则不存在问题:而如果数据用于转载或者商业用途,那么抓取的数据类型就非常关键。
​ 从很多历史案件来看,当抓取的数据是现实生活中的真实数据(比如,营业地址、电话清单)时,是允许转载的。但是,如果是原创数据(比如,意见和评论),通常就会受到版权限制
​ 无论如何,当你抓取某个网站的数据时,请记住自己是该网站的访客,应当约束自己的抓取行为,否则他们可能会封禁你的IP,甚至采取更进一步的法律行动。这就要求下载请求的速度需要限定在一个合理值之内,并且还需要设定一个专属的用户代理来标识自己

2、爬虫定义

​ 网络爬虫(Crawler)又被称为网页蜘蛛(Spider),网络机器人,网页追逐者,它是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。
​ 狭义与广义定义:狭义上指遵循标准的http协议,利用超链接和Web文档检索方法遍历万维网的软件程序;而广义的定义则是能遵循http协议,检索Web文档的软件都称之为网络爬虫。

3、通用爬虫和聚焦爬虫的区别与联系

​ 通用爬虫,搜索引擎和web服务商用的爬虫系统。通用网络爬虫是捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份
​ 聚焦爬虫,是"面向特定主题需求"的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于:聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息

4、url的搜索策略(基于ip地址搜索,广度优先,深度优先,最佳优先)

①基于ip地址搜索

​ 先赋予爬虫一个起始的IP地址,然后根据IP地址递增的方式搜索本口地址段后的每一个WWW地址中的文档,它完全不考虑各文档中指向其它Web站点的超级链接地址。
​ 优点是搜索全面,能够发现那些没被其它文档引用的新文档的信息源。
​ 缺点是不适合大规模搜索。

②广度优先搜索策略
广度优先搜索策略是指在抓取过程中,在完成当前层次的搜索后,才进行下一层次的搜索。这样逐层搜索,依此类推。
该算法的设计和实现相对简单。为覆盖尽可能多的网页,一般使用广度优先搜索方法。

③深度优先搜索策略
深度优先搜索在开发网络爬虫早期使用较多的方法之一,目的是要达到叶结点,即那些不包含任何超链接的页面文件。

​ 从起始页开始在当前HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。当不再有其他超链可选择时,说明搜索已经结束。

④最佳优先搜索策略
最佳优先搜索策略按照一定的网页分析算法,先计算出URL描述文本的目标网页的相似度,设定一个值,并选取评价得分超过该值的一个或几个URL进行抓取。它只访问经过网页分析算法计算出的相关度大于给定的值的网页。
存在的一个问题是,在爬虫抓取路径上的很多相关网页可能被忽略,因为最佳优先策略是一种局部最优搜索算法。因此需要将最佳优先结合具体的应用进行改进,以跳出局部最优点。
有研究表明,这样的闭环调整可以将无关网页数量降低30%-90%。

二、网页的基础知识:

1、url的概念

​ URL(Uniform Resource Locator),即统一资源定位符,也就是我们说的网址,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

2、 http和https

①超文本:hypertext,浏览器里面看到的网页就是超文本解析而成,其网页源代码是一系列html代码,如img表示图片,p指定段落。

②Http基本原理

​ http和https:访问资源需要的协议类型,还有其他的类型,ftp,sftp,smb等
http:hyper text transfer protocol,超文本传输协议,网络传输超文本数据到本地浏览器的传送协议,保证高效而准确的传送超文本文档
​ https : Hyper Text Transfer Protocol over Secure SocketLayer,以安全为目标的http通道,http下加入ssl层
作用:建立一个信息安全通道来保证数据传输的安全,确认网站的真实性

3、http的请求过程

①浏览器中输入url后,浏览器向网站所在服务器发送了一个请求,网站服务器接收请求,并对这个请求进行处理和解析,然后返回对应的响应,传回给浏览器,再通过浏览器解析出来。
②浏览器请求过程。

4、请求,四部分内容:
①请求的网站(request url)
②请求的方法:

a.get请求:
✓ 请求中的参数包含在url里面
✓ 请求提交的数据最多只有1024字节
✓ 百度中输入关键字,wd表示要搜索的关键字

b.post请求:
✓ 表单提交时候发起,用户登录
✓ 数据以表单的形式传输,不会体现在url中
✓ 请求提交的数据没有大小限制
✓ 数据传输更安全(参数不会体现在url中)

③请求头:cookie,user-agent

用来说明服务器要使用的附加信息,比较重要的信息有cookie,user-agent

④请求体:get请求体位空,post请求体为表单数据

5、响应,三部分内容:
①响应状态码:200为ok
python爬虫_第1张图片
②响应头 response header

包含了服务器对请求的应答信息,如content￾type,server,set-cookis等。

③响应体:响应的正文数据,网页源代码,json数据,二进制文件(图片,音频,视频)

爬虫请求后解析的内容就是响应体,响应的正文数据,比如请求网页时,响应体是html代码;请求一张图片时,响应体为图片的二进制数据;json数据等。

6、网页构成:
①html:骨架,决定网页的结构,head节点,title节点等

​ 决定网页的结构和内容(是什么),元素标记头部文件,用元素标记网页名称,用元素标记网页主体,用

元素标记表格等等,段落用p标签表示,布局通过布局标签div嵌套组合合成。

②CSS:皮肤,决定网页的表现样式,放在head里面的style里面
层叠指在html中引用了数个样式文件,并且样式发生冲突时候,浏览器能依据层叠顺序处理。
样式指设定网页的表现样式(什么样子)。将网页样式提取出来方便更改某一类元素的样式,通过

③js:肌肉,网页动画和交互性,script里面

​ Html和Css只是实现静态信息,缺乏交互性。网页的交互和动画效果通过JavaScript实现, JavaScript通过单独的文件形式加载,后缀为js Html中通过

三、爬虫基本的原理:

1、获取网页的源代码(通过请求库发起http请求)
①urllib:
urlopen:最基本的,可以get或者post请求
Request:先声明reques对象,可以加入header信息,再用urlopen打开

#get请求,访问百度
import urllib.request
response=urllib.request.urlopen('http://www.baidu.com') # 发送请求
print(response.read().decode('utf-8'))  #解码后的响应

#post请求
import urllib.parse
import urllib.request
da = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')#urlencode方法将参数字典转换为字符串
response = urllib.request.urlopen('http://httpbin.org/post',data=da)
print(response.read())

​ ②requests:优先考虑使用
​ get请求:param参数
​ post请求:data参数,传表单数据
​ header信息,可以带cookies,agent

# 爬取豆瓣电影分类动漫排行榜并导出到本地
import time
import random
import requests
data1=pd.DataFrame()
for i in range(6):
    print('正在爬取第%s页'%i)
    i=i*20
    qurl="https://movie.douban.com/j/chart/top_list?type=25&interval_id=100%3A90&action=&start="
    url=qurl+str(i)+'&limit=20'
    header={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}
    response=requests.get(url,headers=header)  #requests.get方法
    html=response.content.decode('utf-8')
    df=pd.read_json(html)          #json数据可直接用数据框方法转换
    data1=pd.concat([data1,df])
    time.sleep(random.randint(6,9))
print('爬取完毕')
data2=data1[['rank','title','cover_url','actors','score']].set_index('rank')
data2.to_excel('E:\\迅雷下载\\data.xlsx')

​ ③selenium: page_source

具体内容见爬虫 selenium

2、提取信息(分析网页源代码,提取数据)
①JSON: response.json, pd.read_json
②正则表达式:如何写表达式,find_all
python爬虫_第2张图片

#匹配电话号码和邮箱
import re
import pyperclip
#为电话创建一个正则表达式
phoneRegex = re.compile('\d{8,11}')  #8位
#为E-mail 地址创建一个正则表达式
emailRegex = re.compile('''(
[a-zA-Z0-9_%+-]+ # username
@ # @ symbol
[a-zA-Z0-9-]+ # domain name
\.
[a-zA-Z]{2,4}# dot-something
)''', re.VERBOSE) 				#re.VERBOSE管理复杂文本模式,忽略空白符和注释

# Find matches in clipboard text.
text = str(pyperclip.paste())		#从粘贴板过来的字符串
matches = []
for groups in phoneRegex.findall(text):
    matches.append(groups)   
for groups in emailRegex.findall(text):
    matches.append(groups)
# Copy results to the clipboard.
if len(matches) > 0:
    print('Copied to clipboard:')
    print('\n'.join(matches))
else:
    print('No phone numbers or email addresses found.')

③Beautiful Soup库:两个功能

​ Python的一个HTML解析库,借助网页的结构和属性来解析网页(比正则表达式简单、有效)
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。

​ a.对文档进行解析

from bs4 import BeautifulSoup
soup = BeautifulSoup(html,'lxml') #对html进行解析,完成初始化
print(soup.prettify()) #字符串按标准缩进格式输出,自动进行格式更正

python爬虫_第3张图片

​ b.通过网页的结构和属性提取信息
​ 节点选择器:直接调用节点的名字

soup.head   #选择head节点,默认找到是第一个节点
soup.title  #选择title节点
soup.title.string  #选择节点内的文本

​ 方法选择器:find,find_all

find返回的是首次出现的;findall返回的是所有,列表
1、根据节点的名字选择:name=    #soup.find_all('p'),name可省略
2、根据类名选择:class_=    #soup.find_all(class_='sister')
3、根据id名选择:id=       #soup.find_all(id='link1')

​ CSS选择器:select,工作使用较多

选择的是所有,返回的是列表,select
1、根据节点的名字选择,#soup.select('title')
2、根据类名选择:.类名  #soup.select('.sister')
3、根据ID名选择:#ID名 #soup.select('#link1')
soup.select('p #link2')#组合选择,用空格分开,选择更精准
#天气预报数据抓取
import requests
from bs4 import BeautifulSoup
url='http://www.weather.com.cn/weather/101010100.shtml'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'}
response = requests.get(url,headers=headers)
response.encoding='utf-8'
soup = BeautifulSoup(response.text,'lxml')#对html进行解析,完成初始化
u1_tag=soup.find('ul','t clearfix')   # 使用方法选择器提取信息
li_tag=u1_tag.find_all('li')
for tag in li_tag:
    print(tag.find('h1').string)  # 时间
    print(tag.find('p', 'wea').string)  # 天气
    # 温度的tag格式不统一,做容错
    try:
        print(tag.find('p', 'tem').find('span').string)  # 高温
        print(tag.find('p', 'tem').find('i').string)  # 低温
    except:
        print('没有高温或低温数据')
        pass
    print(tag.find('p', 'win').find('i').string)  # win
    print("_______________ 分割线 ____________________")

3、保存数据(本地,数据库)

data.to_csv('E:\\迅雷下载\\链家信息.csv') #将爬取的结果data导出到本地

四、爬取技巧

​ 1、爬取多页:
​ ①找出url的关系
​ ②从前一个页面找出后一个页面的url
​ ③注意限制爬取速度:time.sleep

# 猎场短评  单页
#步骤解析
import requests
from bs4 import BeautifulSoup
url='https://movie.douban.com/subject/26322642/comments?start=0&limit=20&sort=new_score&status=P'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'}
response = requests.get(url,headers=headers)
response.encoding='utf-8'
soup = BeautifulSoup(response.text,'lxml') #对html进行解析,完成初始化
print(soup.prettify())   #打印出来查看我们要的东西是否在里面,找到内容所在位置
html=soup.select(' .comment-item')  # 切取所需内容所在类名
html[0]   #查看第一列
html[0].find('div',class_="avatar").a['title'] #切出第一个评论人  
html[0].find('span',class_="comment-time")['title'] #切取第一个评论时间
html[0].find('span',class_="short").text #切取第一条评论内容
html[0].find('span',class_="votes").text #切取第一条评论的点赞数

#完整代码,爬取一页
import requests
import pandas as pd 
from bs4 import BeautifulSoup
url='https://movie.douban.com/subject/26322642/comments?start=0&limit=20&sort=new_score&status=P'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'}
response = requests.get(url,headers=headers)
response.encoding='utf-8'
soup = BeautifulSoup(response.text,'lxml')  #对html进行解析,完成初始化
itemslist=[]
html=soup.select(' .comment-item')
for item in html:
    it=[]
    it.append(item.find('div',class_="avatar").a['title']) #评论人    
    it.append(item.find('span',class_="comment-time")['title']) #评论时间
    it.append(item.find('span',class_="short").text) #评论内容
    it.append(item.find('span',class_="votes").text) #点赞数
    itemslist.append(it)
pd.DataFrame(itemslist,columns=['评论人','评论时间','评论内容','点赞数']).set_index('评论人')
#完整代码,爬取多页
import requests
import pandas as pd 
from bs4 import BeautifulSoup
import time
data=pd.DataFrame()
for i in range(10):
    print('正在爬取第%d页'%i)   # 豆瓣查看URL的关系,用for循环爬取多页
    i=i*20
    url='https://movie.douban.com/subject/26322642/comments?start='+str(i)+'&limit=20&sort=new_score&status=P'
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'}
    response = requests.get(url,headers=headers)
    response.encoding='utf-8'
    soup = BeautifulSoup(response.text,'lxml')  #对html进行解析,完成初始化
    itemslist=[]
    html=soup.select(' .comment-item')
    for item in html:
        it=[]
        it.append(item.find('div',class_="avatar").a['title']) #评论人    
        it.append(item.find('span',class_="comment-time")['title']) #评论时间
        it.append(item.find('span',class_="short").text) #评论内容
        it.append(item.find('span',class_="votes").text) #点赞数
        itemslist.append(it)
        df=pd.DataFrame(itemslist)
    data=pd.concat([data,df])
    time.sleep(6)
data.columns=['评论人','评论时间','评论内容','点赞数']
data.set_index('评论人')

2、动态渲染页面的爬取:
①查找url的关系
②selenium:驱动浏览器执行特定的动作,获得网页源代码,可见即可爬
③步骤 1.节点的定位,执行操作
2.获得网页源代码
3.信息的提取

#爬取京东手机商品 爬取一页
from bs4 import BeautifulSoup
import os
import time 
os.chdir(r'D:\CDA数分学习资料\python\爬虫') #当chormedriver和data文件放在一起不需要指定位置 
browser=webdriver.Chrome()  # 打开浏览器
url='https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&wq=%E6%89%8B%E6%9C%BA&pvid=7006616bd0b543cd86d45af18335c009'
browser.get(url)
browser.maximize_window()   # 最大化浏览器
input=browser.find_element_by_id('key') #找搜索的输入框 
input.clear()  # 清理输入框
input.send_keys('手机')  # 输入搜索词 手机
browser.find_element_by_class_name('button').click() # 输入手机后回车
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') #下拉滚动条
time.sleep(5)
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') #再次下拉滚动条
time.sleep(10)
html=browser.page_source # 网页源码
soup = BeautifulSoup(html, 'html.parser') #内置的标准库进行网页的解析
itemslist=[]  
items=soup.find_all('li',class_='gl-item')  # 找出所有(li节点和类名为gl—item)
for item in items:
    it=[]
    it.append(item.find('div',class_='p-name p-name-type-2').find('em').text)#商品名称
    it.append(item.find('div',class_='p-price').find('i').text)# 价格
    it.append(item.find('span',class_='J_im_icon').text) #店家名称
    itemslist.append(it)  
df=pd.DataFrame(itemslist,columns=['商品名称','价格','店家']).set_index('商品名称')
df
#爬取京东手机商品 爬取多页
import pandas as pd
from bs4 import BeautifulSoup
browser=webdriver.Chrome() 
url='https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&wq=%E6%89%8B%E6%9C%BA&pvid=7006616bd0b543cd86d45af18335c009'
browser.get(url)
browser.maximize_window()  
input=browser.find_element_by_id('key')#
input.clear()
input.send_keys('手机')
browser.find_element_by_class_name('button').click()#回车
data=pd.DataFrame()
for i in range(5):
    print('正在爬取第%d页'%i)
    browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    time.sleep(5)
    browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    time.sleep(5)
    html=browser.page_source
    soup = BeautifulSoup(html, 'html.parser')#内置的标准库进行网页的解析
    itemslist=[]
    items=soup.find_all('li',class_='gl-item')
    for item in items:
        it=[]
        it.append(item.find('div',class_='p-name p-name-type-2').find('em').text)#商品名称
        it.append(item.find('div',class_='p-price').find('i').text)#价格
        if item.find('span',class_='J_im_icon')==None:  #店家名称
            it.append('京东自营')
        else:
            it.append(item.find('span',class_='J_im_icon').text)
        itemslist.append(it)
    df=pd.DataFrame(itemslist)
    data=pd.concat([data,df])
    browser.execute_script('window.scrollTo(0,10000)')
    time.sleep(5)
    browser.find_element_by_class_name('pn-next').click()
    time.sleep(5)
data.columns=['商品名称','价格','店家']
data=data.set_index('商品名称')

五、反爬虫:

​ 1.使用user-agent模拟浏览器,header加入
​ 2.多账号登录:加入cookies,cookies池
​ 3.代理:突破ip的限制,ip池,requests.get(url,proxies=proxies,timeout=10)
​ 4.验证码OCR识别,机器学习方法,接入打码平台
​ 5.使用selenium完全模拟浏览器
​ 6.抓包软件分析



你可能感兴趣的:(Python)