玩转python爬虫,从简易到复杂

本文详细介绍了Python爬虫的常用模块和方法,包括urllib、requests的使用,以及数据解析方法如正则表达式、XPath和BeautifulSoup。还深入探讨了处理动态加载数据的策略,如Selenium和PhantomJS,并介绍了Scrapy框架的基本操作,如持久化存储、数据处理管道和分布式爬虫。最后提到了登录操作、Cookie管理和代理设置。
摘要由CSDN通过智能技术生成

一. urllib

urllib是python中自带的一个基于爬虫的模块

作用:可以使用代码模拟浏览器发起请求

使用流程:

  • 指定url
  • 发起请求
  • 获取页面数据
  • 持久化存储

 

1. 第一个urllib爬虫程序

# 需求: 爬取搜狗首页的页面数据
import urllib.request
# 1. 指定url
url = 'https://www.sogou.com/'

# 2. 发起请求:urlopen可以根据指定的url发起请求,并返回一个响应对象
response = urllib.request.urlopen(url=url)

# 3. 获取页面数据:read函数返回的就是响应对象中存储的页面数据
page_text = response.read()

# 4. 进行持久化存储
with open('./sougou.html', 'wb') as f:
    f.write(page_text)
    print("Done")

 

2. urllib编码处理

# 需求:爬去指定词条所对应的页面数据
import urllib.request
import urllib.parse

# 指定url
url = 'https://www.sogou.com/web?query='

# url特性:url不可以存在非ASCII编码的字符数据,汉字并不在ASCII编码当中
word = urllib.parse.quote("宝马")
url += word

# 发请求
response = urllib.request.urlopen(url=url)

# 获取页面数据
page_text = response.read()

# 持久化存储
with open('./bmw.html', 'wb') as f:
    f.write(page_text)

 

3. urllib的post请求

# urllib模块发起的post请求
# 需求:爬取百度翻译的翻译结果
import urllib.request
import urllib.parse

# 1. 指定url
url = 'https://fanyi.baidu.com/sug'

# post请求携带的参数进行处理
# 流程:
# 1). 将post请求参数封装到字典
data = {
    'kw': "苹果"
}

# 2). 使用parse模块中的urlencode(返回值类型为str)进行编码处理
query = urllib.parse.urlencode(data)

# 3). 将步骤2的编码结果转换成byte类型
data = query.encode()

# 2. 发起post请求:urlopen函数的data参数表示的就是经过处理之后的post请求携带的参数
response = urllib.request.urlopen(url=url, data=data)

print(response.read())

 

 

 

二. requests模块

requests是python原生的一个基于网络请求的模块,模拟浏览器发起请求

 

1. requests-get请求:

1)简单的get请求

import requests
# 需求:爬取搜狗首页的页面数据
url =  'https://www.sogou.com/'

# 发起get请求,get方法会返回请求成功的相应对象
response = requests.get(url=url)

# 获取响应中的数据值:text可以获取响应对象中字符串形式的页面数据
page_data = response.text

# response对象中其他的重要属性
# content或取得时response对象中二进制(byte)类型的页面数据
# print(response.content)
# 返回一个响应状态码
# print(response.status_code)
# 返回响应头信息
# print(response.headers)
# 获取请求的url
# print(response.url)

# 持久化操作
with open('./sougou_requests.html', 'w',encoding='utf-8') as f:
    f.write(page_data)

 

2)requests携带参数的get请求

方式1:

# requests模块处理携带参数的get请求
# 需求:指定一个词条,获取搜狗搜索结果所对应的页面数据

# 1. 指定url
url = 'https://www.sogou.com/web?query=宝马&ie=utf-8'

response = requests.get(url=url)

page_text = response.text

with open('./bmw_requests.html', 'w', encoding='utf-8') as f:
    f.write(page_text)

方式2:

# requests模块处理携带参数的get请求
# 需求:指定一个词条,获取搜狗搜索结果所对应的页面数据

url = 'https://www.sogou.com/web'
# 将参数封装到字典中
params = {
    'query': '宝马',
    'ie': 'utf-8'
}

response = requests.get(url=url, params=params)

print(response.text)

 

3)自定义请求头信息

# 自定义请求头信息
import requests

url = 'https://www.sogou.com/web'
params = {
    'query': '宝马',
    'ie': 'utf-8'
}

# 自定义请求头信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}

response = requests.get(url=url, params=params, headers=headers)

print(response.text)

 

2. requests的post请求

import requests

# 1. 指定post请求的url
url = 'https://accounts.douban.com/login'

# 2. 发起post请求
data = {
    'source': 'movie',
    'redir': 'https://movie.douban.com/',
    'form_email' : 'xxx@qq.com',
    'form_password' : 'xxx',
    'login' : '登录'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
response = requests.post(url=url, data=data)

# 3. 获取响应对象中的页面数据
page_text = response.text

# 4. 持久化操作
with open('./douban_request.html', 'w', encoding='utf-8') as f:
    f.write(page_text)

 

3. ajax的get请求

import requests

url = 'https://movie.douban.com/j/chart/top_list?'

# 封装ajax的get请求中携带的参数
params = {
    'type' : '13',
    'interval_id' : '100:90',
    'action': '',
    'start': '0',
    'limit': '20',
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
response = requests.get(url, params=params, headers=headers)

print(response.text)

 

4. ajax的post请求

import requests

# 1. 指定url
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'

# 处理post请求的参数
data = {
    'cname': '',
    'pid': '',
    'keyword': '上海',
    'pageIndex': 1,
    'pageSize': 10
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}

# 2. 发起基于ajax的post请求
response = requests.post(url=post_url, data=data, headers=headers)
print(response.text)

 

5. 综合实战

import requests
import os

# 创建一个文件夹
if not os.path.exists('./zhihu_pages'):
    os.mkdir('./zhihu_pages')

word = input('enter a word: ')

# 动态指定页码的范围
start_pageNum = int(input('enter a start pageNum: '))
end_pageNum = int(input('enter a end pageNum: '))

# 指定url:设计成一个具有通用的url
url = 'http://zhihu.sogou.com/zhihu'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}

for page in range(start_pageNum, end_pageNum+1):
    params = {
        'query': word,
        'page': page,
        'ie': 'utf-8'
    }
    response = requests.get(url=url, params=params, headers=headers)
    
    # 获取响应中的页面数据
    page_text = response.text
    
    # 进行持久化存储
    filename = word + str(page) + '.html'
    filePath = 'zhihu_pages/' + filename
    with open(filePath, 'w', encoding='utf-8') as f:
        f.write(page_text)
        print("文件第%s页数据写入成功" % page)

 

6. requests携带cookie

cookie作用:服务器端使用cookie来记录客户端的状态信息

实现流程:1.执行登陆操作(获取cookie);2.在发起个人主页请求时,需要将cookie携带到该请求中

import requests

# 获取session对象
session = requests.session()

# 1. 发起登录请求:将cookie获取,并存储到session对象中
login_url = 'https://accounts.douban.com/login'
data = {
    'source': 'None',
    'redir': 'https://www.douban.com/people/186539740/',
    'form_email' : 'xxxx@qq.com',
    'form_password' : 'xxx',
    'login' : '登录'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
# 使用session发起post请求
login_response = session.post(url=login_url, data=data, headers=headers)

# 2. 对个人主页发起请求(session(cookie)),获取相应页面数据
url = 'https://www.douban.com/people/186539740/'
response = session.get(url=url, headers=headers)
page_text = response.text

with open('./douban_person1.html', 'w', encoding='utf-8') as f:
    f.write(page_text)

 

7. requests模块的代理操作

代理分类:1.正向代理:代替客户端获取数据;2.反向代理:代理服务器端提供数据

免费代理ip的网站提供商:www.goubanjia.com; 快代理;西祠代理

import requests

url = 'https://www.baidu.com/s?ie=utf-8&wd=ip'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
# 将代理ip封装到字典当中
proxy = {
    'http': '39.137.77.66:8080'
}
# 更换网路IP
response = requests.get(url=url, proxies=proxy, headers=headers)

with open('./proxy1.html', 'w', encoding='utf-8') as f:
    f.write(response.text)

 

8. 数据解析

1)正则表达式

# 需求:使用正则对糗事百科中的图片数据进行解析和下载
import requests
import re
import os

# 指定url
url = 'https://www.qiushibaike.com/pic/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
# 发起请求
response = requests.get(url=url, headers=headers)

# 获取页面数据
page_text = response.text

# 数据解析
img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>', page_text, re.S)

# 创建一个存储图片数据的文件夹
if not os.path.exists('./imgs_qiushi'):
    os.mkdir('imgs_qiushi')

for url in img_list:
    # 将图片的url进行拼接,拼接成一个完整的url
    img_url = 'https:' + url
    # 持久化存储:存储的是图片的数据,并不是url
    # 获取图片二进制的数据值
    img_data = requests.get(url=img_url, headers=headers).content
    imgName = url.split('/')[-1]
    imgPath = 'imgs_qiushi/' + imgName
    with open(imgPath, 'wb') as f:
        f.write(img_data)
        print(imgName + "写入完成")

 

2)xpath

xpath在爬虫中的使用流程:

(1) 下载:pip install lxml

(2) 导包:from lxml import etree

(3) 创建etree对象进行指定数据的解析

  • 本地:etree = etree.parse("本地文件路径")
  •            etree.xpath("xpath表达式")
  • 网络:etree = etree.HTML("网络请求到的页面数据")
  •            etree.xpath("xpath表达式")

 

常用的xpath表达式:

(1)属性定位:

# 找到class属性值为song的div标签:"//div[@class='song']"

(2)层级&索引定位:

# 找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a:"//div[@class='tang']/ul/li[2]/a"

(3)逻辑运算:

# 找到href属性值为空且class属性值为du的a标签:"//div[@href='' and @class='du']"

(4)模糊匹配:

# "//div[contains(@class, 'ng')]"

# "//div[starts-with(@class, 'ta')]"

(5)取文本:

# /表示获取某个标签下的文本内容

# //表示获取某个标签下的文本内容和所有子标签下的文本内容

# "//div[@class='song']/p[1]/text()"

# "//div[@class='tang']//text()"

(6)取属性:

# "//div[@class='tang']//li[2]/a/@href"

# 需求:使用xpath对段子网中的段子内容和标题进行解析,并持久化存储
import requests
from lxml import etree

# 1. 指定url
url = 'https://ishuo.cn/joke'

# 2. 发起请求
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}
response = requests.get(url=url, headers=headers)

# 3. 获取页面内容
page_text = response.text

# 4. 数据解析
tree = etree.HTML(page_text)
# 获取所有的li标签,
li_list = tree.xpath("//div[@id='list']/ul/li")
with open('./duanzi.txt', 'w', encoding='utf-8') as f:
    for li in li_list:
        content = li.xpath("./div[@class='content']/text()")[0]
        title = li.xpath("./div[@class='info']/a/text()")[0]
        # 5. 持久化
        f.write(title + ":" + content + "\n\n")

 

3)bs4

核心思想:将html文档转换成Beautiful对象,然后调用该对象中的属性和方法进行html稳定指定内容的定位查找。

属性和方法:

(1)根据标签名查找

soup.a  # 只能找到第一个符合要求的标签

(2)获取属性

soup.a.attrs  # 获取a所有的属性和属性值,返回一个字典

soup.a.attrs['href']  # 获取href属性

soup.a['href']  # 也可以简写为这种形式

(3)获取内容

soup.a.string

soup.a.text

soup.a.get_text()

注意:如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容

(4)find:找到第一个符合要求的标签

soup.find('a')  # 找到第一个符合要求的

soup.find('a', title='xxx')

soup.find('a', alt='xxx')

soup.find('a', class='xxx')

soup.find('a', id='xxx')

(5)find_all:找到所有符合要求的标签

soup.find_all('a')

soup.find_all(['a', 'b'])   # 找到所有的a和b标签

soup.find_all('a', limit=2)  # 限制前两个

(6)根据选择器选择指定的内容

select:soup.select('#feng')

- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器

层级选择器:

div .dudu #lala ,meme .xixi

div > p > a > .lala

注意:select选择器返回永远是列表,需要通过下标提取指定的对象

# 需求:爬取古诗文网中三国小说里的标题和内容
import requests
from bs4 import BeautifulSoup
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
}

# 根据url获取页面内容中指定的标题所对应的文章内容
def get_content(url):
    content_page = requests.get(url=url, headers=headers).text
    soup = BeautifulSoup(content_page, 'lxml')
    div = soup.find('div', class_='chapter_content')
    return div.text
    
page_text = requests.get(url=url, headers=headers).text

soup = BeautifulSoup(page_text, 'lxml')
a_list = soup.select('.book-mulu > ul > li > a')

with open('./threekingdoms.txt', 'w', encoding='utf-8') as f:
    for a in a_list:
        title = a.string
        content_url = 'http://www.shicimingju.com' + a['href']
        content = get_content(content_url)
        f.write(title + ":\n" + content + "\n\n\n")
        print(title + ": 已被写入")

 

9. 处理页面动态加载数据的爬取

1)selenum:三方库。可以实现让浏览器完成自动化的操作

(1)环境搭建

a. 安装: pip install selenium

b. 获取浏览器的驱动程序:

谷歌浏览器驱动下载地址:chromedriver.storage.googleapis.com/index.html

下载的驱动程序必须和浏览器的版本统一,对照表参照:http://blog.csdn.net/huilan_same/article/details/51896672

from selenium import webdriver

# 创建一个浏览器对象executable_path驱动的路径
b = webdriver.Chrome(executable_path='./chromedriver')

#get方法可以指定一个url,让浏览器进行请求
url = 'https://www.baidu.com'
b.get(url)

# 使用下面的方法,查找指定的元素进行操作即可
# find_element_by_id   根据id找节点
# find_elements_by_name   根据name找
# find_elements_by_xpath   根据xpath查找
# find_elements_by_tag_name   根据标签找
# find_elements_by_class_name   根据class名字查找

# 让百度进行指定词条的搜索
text = b.find_element_by_id('k
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值