当前位置:   article > 正文

python爬虫学习笔记(基于尚硅谷)_python爬虫保存在思源笔记

python爬虫保存在思源笔记
01.urllib

通过一个程序,根据Url进行爬取网页,获取有用信息 使用程序模拟浏览器,去向服务器发送请求,获取响应信息

反爬手段

1.User‐Agent 2.代理IP 3.验证码访问 4.数据加密

5.动态加载网页 网站返回的是js数据 并不是网页的真实数据

urllib一个类型六个方法
import urllib.request

url = 'http://baidu.com'

response = urllib.request.urlopen(url)

#response是HTTPResponse的类型
'print(type(response))'

#按字节读
content1 = response.read(5)

#按行读
content2 = response.readline()
print(content2)

content3 = response.readlines()
print(content3)

#状态码
print(response.getcode())

#地址
print(response.geturl())

#获取状态信息
print(response.getheaders())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
urllib下载
import urllib.request

#页面
url_page = 'http://www.baidu.com'
urllib.request.urlretrieve(url_page,'baidu.html')

#图片
url_img = 'https://tse3-mm.cn.bing.net/th/id/OIP-C.mNqPTNrIJLPdTDtgeTE7MAHaLH?w=186&h=279&c=7&r=0&o=5&dpr=1.5&pid=1.7'
urllib.request.urlretrieve(url_img,filename='lisa.jpg')

#视频
url_video = '视频url'
urllib.request.urlretrieve(url_video,'cat.mp4')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
请求对象定制
import urllib.request

url = 'https://cn.bing.com/search?q=%E5%91%A8%E6%9D%B0%E4%BC%A6&form=ANNTH1&refig=9e63813a16cf4a9fb53ed3f604bcb4f4'


headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}

#请求对象定制 urlopen不能存字典

#请求对象的定制 ua反爬
request = urllib.request.Request(url=url,headers = headers)

response = urllib.request.urlopen(request)

content = response.read().decode('UTF-8')
print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
get请求方式:urllib.parse.quote()
import urllib.request
import urllib.parse

#获取网页源码
url = 'https://www.baidu.com/s?wd='

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}

#将周杰伦变成unicod
name = urllib.parse.quote('周杰伦')
#根据值获取
url = url + name

request = urllib.request.Request(url=url,headers=headers)

response = urllib.request.urlopen(request)

content = response.read().decode('utf-8')

print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
get请求方式:urllib.parse.urlencode()
import urllib.request
import urllib.parse

base_url = 'https://www.baidu.com/s?'

data = {
    'wd':'周杰伦',
    'sex':'男',
    'location':'中国台湾'
}

new_data = urllib.parse.urlencode(data)
url = base_url + new_data

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}

request = urllib.request.Request(url = url,headers = headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
post请求方式
import urllib.request

url = 'https://fanyi.baidu.com/sug'

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}

data = {
    'kw':'spider'
}

#post请求的参数 必须要进行编码
data = urllib.parse.urlencode(data).encode('utf-8')

request = urllib.request.Request(url=url,data=data,headers=headers)

response = urllib.request.urlopen(request)

content = response.read().decode('utf-8')

import json
obj = json.loads(content)
print(obj)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

总结:post和get区别?

1:get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法

2:post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法

ajax豆瓣电影前十页 get请求

ajax是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。

这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

#下载豆瓣电影前10页数据
#1、请求对象定制
#2、获取响应数据
#3、下载数据
import urllib.parse
import urllib.request

def creat_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=13&interval_id=100%3A90&action=&'

    data = {
        'start':(page-1)*20,
        'limit':20
    }

    data = urllib.parse.urlencode(data)

    url = base_url + data

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
    }

    request = urllib.request.Request(url=url,headers=headers)
    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

def down_load(page,content):
    with open('douban'+ str(page) +'.json','w',encoding='utf-8')as fp:
        fp.write(content)

#入口(可选)
if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page+1):
        #每一页都有自己请求对象的定制
        request = creat_request(page)
        content = get_content(request)
        #下载
        down_load(page,content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
ajax 请求kfc网站 post请求
import urllib.request
import urllib.parse

def create_request(page):
    base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'

    data = {
        'cname': '宜昌',
        'pid':'',
        'pageIndex': page,
        'pageSize': '10'
    }

    data = urllib.parse.urlencode(data).encode('utf-8')

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
        'Cookie':'route - cell = ksa;ASP.NET_SessionId = 5lvicybh0c1hvcltu04vpz3m;Hm_lvt_1039f1218e57655b6677f30913227148 = 1682253815;Hm_lpvt_1039f1218e57655b6677f30913227148 = 1682253815;SERVERID = 6ee43946432b1a5105f8c6178eb14f6d | 1682260334 | 1682260068'
    }

    request = urllib.request.Request(url=base_url,headers=headers,data=data)


def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

def down_load(page,content):
    with open('kfc_'+str(page)+'.json','w',encoding='utf-8')as fp:
        fp.write(content)

if __name__ == '__main__':
    start_page = int(input('请输入起始页码:'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page+1):
        request = create_request(page)

        content = get_content(request)

        down_load(page,content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
异常处理
import urllib.request
import urllib.error

#url = 'https://blog.csdn.net/weixin_46211269/article/details/126121311'

url = 'http://www.goudan1111.com'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
    'Cookie': 'route - cell = ksa;ASP.NET_SessionId = 5lvicybh0c1hvcltu04vpz3m;Hm_lvt_1039f1218e57655b6677f30913227148 = 1682253815;Hm_lpvt_1039f1218e57655b6677f30913227148 = 1682253815;SERVERID = 6ee43946432b1a5105f8c6178eb14f6d | 1682260334 | 1682260068'
}

try:
    request = urllib.request.Request(url=url,headers=headers)
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    print(content)
except urllib.error.HTTPError:
    print('系统正在升级')

except urllib.error.URLError:
    print('系统正在升级')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
'
运行
cookie登录
#数据采集时,需要绕过登录,然后进入到某个页面
#个人信息页面是utf-8 但还是报编码错误 因为没有进入到个人页面 而是跳转
#到登录页面 登录页面不是utf-8
import urllib.request

url = 'https://weibo.com/u/5398458536'

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}
request = urllib.request.Request(url=url,headers=headers)

response = urllib.request.urlopen(request)

content = response.read().decode('gb2312')

print(content)

#数据保存
with open('weibo.html','w',encoding='gb2312')as fp:
    fp.write(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
Handler处理器

定制更高级的请求头(随着业务逻辑的复杂 请求对象的定制已经满足不了我们的需求(动态cookie和代理 不能使用请求对象的定制)

import urllib.request
url = 'http://www.baidu.com'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}

request = urllib.request.Request(url=url,headers=headers)

#handler bulid_open open
#获取handler对象
handler = urllib.request.HTTPHandler()

#获取opener对象
opener = urllib.request.build_opener(handler)

#调用open方法
response = opener.open(request)

content = response.read().decode('utf-8')

print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
代理的基本使用

代码配置代理

  1. 创建Reuqest对象
  2. 创建ProxyHandler对象
  3. 用handler对象创建opener对象
  4. 使用opener.open函数发送请求
import urllib.request
url = 'http://www.baidu.com/s?wd=ip'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}

request = urllib.request.Request(url=url,headers=headers)

proxies={
    'http':'58.20.184.187:9091'
}

handler = urllib.request.ProxyHandler(proxies=proxies)

opener  = urllib.request.build_opener(handler)

response = opener.open(request)

content = response.read().decode('utf-8')

with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
代理池
import urllib.request
proxies_pool = [
    { 'http':'118.24.219.151:16817' },
    { 'http':'118.24.219.151:16111'}
]
#从代理池中随机选择一个
import random

proxies = random.choice(proxies_pool)
#后面用handler包装
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行
02.解析

xpath 使用 Ctrl + Shlft + x

#xpath解析
#1.本地文件                                            etree.parse
#2.服务器响应的数据 response.read().decode('utf-8)       etree.HTML()
  • 1
  • 2
  • 3
'
运行
xpath基本语法:

1.路径查询

查找所有子孙节点,不考虑层级关系

找直接子节点

2.谓词查询

div[@id]

div[@id=“maincontent”]

3.属性查询

@class

4.模糊查询

div[contains(@id, “he”)]

div[starts‐with(@id, “he”)]

5.内容查询

div/h1/text()

6.逻辑运算

div[@id=“head” and @class=“s_down”]

title | price

#解析本地文件
tree = etree.parse('070解析xpath基本使用.html')

#tree.xpath('xpath路径')

#查找ul下的li
li_list = tree.xpath('//body/ul/li')

#查找所有有id的属性的li标签
#text()获取标签中的内容
li_list = tree.xpath('//ul/li[@id]/text()')

#找到id为11的li标签   注意引号
li_list = tree.xpath('//ul/li[@id="11"]/text()')

#查找到id为11的li标签的class的属性值
li_list = tree.xpath('//ul/li[@id="11"]/@class')

#查找id中包含1的li标签
li_list = tree.xpath('//ul/li[contains(@id,"1")]/text()')

#查询id的值以1开头的li标签
li_list = tree.xpath('//ul/li[starts-with(@id,"c")]/text()')

#查询id为11和class为c1的
li_list = tree.xpath('//ul/li[@id="11" and @class="c1"]/text()')

#
li_list = tree.xpath('//ul/li[@id="11"]/text() | //ul/li[@id="12"]/text()')

#判断列表长度
print(li_list)
print(len(li_list))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
综合使用xpath解析
#获取网站源码
#解析  解析服务器响应的文件 etree.HTML
#打印
import urllib.request

url = 'https://www.baidu.com/'
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}
requests = urllib.request.Request(url=url,headers=headers)

response = urllib.request.urlopen(requests)

content = response.read().decode('utf-8')

#解析网页源码 获取要的数据
from lxml import etree

#解析服务器响应文件
tree = etree.HTML(content)

#获取想要的数据  xpath的返回值是列表类型的数据
#浏览器可直接复制获取xml
result = tree.xpath('//input[@id="su"]/@value')[0]
print(result)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
站长素材网站图片爬取
#需求 下载前10页图片
#https://sc.chinaz.com/tupian/qinglvtupian.html
#https://sc.chinaz.com/tupian/qinglvtupian_2.html
import urllib.request
from lxml import etree

def creat_request(page):
    if(page == 1):
        url = 'https://sc.chinaz.com/tupian/qinglvtupian.html'
    else:
        url = 'https://sc.chinaz.com/tupian/qinglvtupian_'+str(page)+'.html'

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
    }
    request =urllib.request.Request(headers=headers,url=url)
    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

def down_load(content):
#  下载图片

    tree = etree.HTML(content)
    name_list = tree.xpath('//div[@class="container"]//img/@alt')
#一般涉及图片的网站都会进行懒加载
    img_list = tree.xpath('//div[@class="container"]//img/@data-original')
    for i in range(len(name_list)):
        name = name_list[i]
        img = img_list[i]
        url = 'https:' + img
#   urllib.request.urlretrieve('图片地址','文件名字')
        urllib.request.urlretrieve(url=url,filename='./loveImg/'+name+'.jpg')
#   .loveImg为目录名 放在...目录下
if __name__ == '__main__':
    start_page = int(input("请输入起始页码"))
    end_page = int(input("请输入结束页码"))

    for page in range(start_page,end_page+1):
        #请求对象定制
        request = creat_request(page)
        # 获取网页源码
        content = get_content(request)
        # 下载
        down_load(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
JSONpath基本语法

在这里插入图片描述

缺点:无法解析服务器响应的数据

案例:

{ "store": {
    "book": [
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

语法:

obj = json.load(open('073解析jsonpath.json','r',encoding='utf-8'))
#书店所有书的作者
author_list = jsonpath.jsonpath(obj,'$.store.book[*].author')

#所有的作者
author_list = jsonpath.jsonpath(obj,'$..author')

#store下的所有元素
tag_list = jsonpath.jsonpath(obj,'$.store.*')

#store下所有的price
price_list = jsonpath.jsonpath(obj,'$.store..price')

#第三个书
book = jsonpath.jsonpath(obj,'$..book[2]')

#最后一本书
book = jsonpath.jsonpath(obj,'$..book[(@.length-1)]')

#前两本书
book_list = jsonpath.jsonpath(obj,'$..book[0,1]')
book_list = jsonpath.jsonpath(obj,'$..book[:2]')

#过滤出所有包含isbn的书  条件过滤需要在()前加一个?
book_list = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]')

#那本书超过10块钱
book_list = jsonpath.jsonpath(obj,'$..book[?(@.price>10)')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
JSONpath解析淘票票网站城市
import urllib.request
url = 'https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1687975134652_108&jsoncallback=jsonp109&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'

headers = {
    'Cookie':'t=a7d009fb8c7d40083be5844676f3955e; cookie2=14f2996b749e6492ee3a6c304cdf58f0; v=0; _tb_token_=f8514e7636eee; cna=Aa7CHMZlFjsCAXWWBoxRWAzg; xlly_s=1; tb_city=110100; tb_cityName="sbG+qQ=="; tfstk=dugJF7fyJKvkEwApr8KD88y1fndDm4hyZYl1-J2lAxHxQYdzxgmov9ex1QykY3kKDvM4q8gKTwFIOvRzKQ-mabzURdvgJFcraZVVGyF6nFGRS0JMIFYMVsaped0hBJmGjNfNSdT5oA3QNHwZ0_nAGKPz2RGvbw_pv76gBb1dJwgxquBaoV099e6gBWjWMIIFYuNq8_x0_; l=fBE4_1-lN4I9l8kXBO5BFurza77TzIRb81PzaNbMiIEGa6tP9FwyqNC1pheDWdtjgT5xsetrip0J_dFyl-UU-dsWHpfuKtyuJev68eM3N7AN.; isg=BLS04fS1bHu-f_i3iogL2Ff9hXImjdh3ZG1PEk4VnD_CuVUDdpuRBtx3OfFhRhDP',
    'Referer':'https://dianying.taobao.com/?spm=a1z21.3046609.city.1.32c0112aTVArVg&city=110100'
}
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
#切割 json不能有多余的括号
content = content.split('(')[1].split(')')[0]

with open('074解析jsonpath淘票票.json','w',encoding='utf-8')as fp:
    fp.write(content)

import json
import jsonpath

obj = json.load(open('074解析jsonpath淘票票.json','r',encoding='utf-8'))
city_list = jsonpath.jsonpath(obj,'$..regionName')
print(city_list)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
BeautifulSoup(bs4)

主要功能也是解析和提取数据

缺点:效率没有lxml的效率高

优点:接口设计人性化,使用方便

BeautifulSoup基本用法

from bs4 import BeautifulSoup
#解析本地文件 来将bs4的基础语法进行讲解
#默认gbk打开时需要指定编码
soup = BeautifulSoup(open('075解析bs4的基本使用.html',encoding='utf-8'),'lxml')
#根据标签名查找节点
#找到的是第一个符合条件的数据
print(soup.a)
#获取标签的属性和属性值
print(soup.a.attrs)

#bs4的一些函数
#(1)find
#返回第一个符合条件的数据
print(soup.find('a'))
#根据title值来找到对应的标签对象
print(soup.find('a',title="a2"))
#根据class的值来找到对应的标签对象   注意class需要添加下划线
print(soup.find('a',class_="a2"))

#(2)find_all  返回的是一个列表 并且返回了所有a的标签
print(soup.find_all('a'))
#如果想获取多个标签的数据 那么需要find_all的参数中添加列表的数据
print(soup.find_all(['a','span']))
#limit查找前几个数据
print(soup.find_all('li',limit=2))

#(3)select(推荐)  返回一个列表 并且返回多个数据
print(soup.select('a'))
#可以通过.代表class  类选择器 #代表id
print(soup.select('.a2'))
print(soup.select('#li'))
#属性选择器--通过属性寻找对应标签
#查找到li标签中有id的标签
print(soup.select('li[id]'))
#查找到li标签中id为l2的标签
print(soup.select('li[id="l2"]'))
#层级选择器
#   后代选择器
#找到div下的li
print(soup.select('div li'))
#子代选择器
#   某标签的第一级子标签
print(soup.select('div > ul > li'))
#找到a标签和li标签的所有对象
print(soup.select('a,li'))

#节点信息
#   获取节点内容
obj = soup.select('#d1')[0]
#如果标签对象中 只有内容 那么string和get_text()都可以使用
#如果标签对象中 除了内容还有标签 那么string获取不到数据
print(obj.string)
print(obj.get_text())

#节点的属性
obj = soup.select('#p1')[0]
#name是标签的名字
print(obj.name)
#将属性值左右一个字典返回
print(obj.attrs)

#获取节点属性
obj = soup.select('#p1')[0]
print(obj.attrs.get('class'))
print(obj.get('class'))
print(obj['class'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
Bs4爬取星巴克
import urllib.request
url = 'https://www.starbucks.com.cn/menu/'
response = urllib.request.urlopen(url)
content = response.read().decode('utf-8')

from bs4 import BeautifulSoup

soup = BeautifulSoup(content,'lxml')
#xpath路径://ul[@class="grid padded-3 product"]//strong
name_list = soup.select('ul[class="grid padded-3 product"] strong')
for name in name_list:
    print(name.get_text())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
03.selenium无图形化浏览器

模拟浏览器功能,自动执行网页中的js代码,实现动态加载

基本使用
from selenium import webdriver
#创建浏览器操作对象
path = 'chromedriver.exe'
browser = webdriver.Chrome(path)

#访问网站
url = 'https://www.JD.com'
browser.get(url)
#获取网页源码
content = browser.page_source
print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
元素定位
#根据id找到对象  常用
button = browser.find_element_by_id('su')
#根据标签属性的属性值来获取对象
button = browser.find_element_by_name('wd')
#根据xpath语句来获取对象   常用
button = browser.find_element_by_xpath('//input[@id="su"]')
#根据标签的名字获取对象
button = browser.find_element_by_tag_name('input')
#使用css语法获取对象   常用
button = browser.find_element_by_css_selector('#su')
#根据链接文本获取
button = browser.find_element_by_link_text('新闻')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
元素信息
input = browser.find_element_by_id('su')
#获取标签属性
print(input.get_attribute('class'))
#获取标签名字
print((input.tag_name))
#获取元素文本
a=browser.find_element_by_link_text('新闻')
print(a.text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
自动化交互
#获取文本框对象
input = browser.find_element_by_id('kw')
#文本框输入周杰伦
input.send_keys('周杰伦')
time.sleep(2)
#获取百度一下按钮
button = browser.find_element_by_id('su')
#点击按钮
button.click()
time.sleep(2)
#滑倒底部
js_bottom = 'document.documentElement.scrollTop=100000'
browser.execute_script(js_bottom)
time.sleep(2)
#获取下一页按钮
next = browser.find_element_by_xpath('//a[@class="n"]')
next.click()
time.sleep(2)
#回到上一页
browser.back()
time.sleep(2)
#回到下一页
browser.forward()
time.sleep(3)
#退出
browser.quit()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
Phantomjs无界面浏览器
from selenium import webdriver
path = 'phantomjs.exe'
browser = webdriver.PhantomJS(path)
url = 'https://www.baidu.com'
browser.get(url)
  • 1
  • 2
  • 3
  • 4
  • 5
chrome handless无界面浏览器

封装

#封装的handless
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def share_browser():
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable‐gpu')

    # path是你自己chrome浏览器的文件路径
    path = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
    chrome_options.binary_location = path

    browser = webdriver.Chrome(chrome_options=chrome_options)
    return browser
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
'
运行

封装调用

browser = share_browser()
url = 'https://www.baidu.com'
browser.get(url)
  • 1
  • 2
  • 3
04.requests

文档:

官方文档 Requests: 让 HTTP 服务人类 — Requests 2.18.1 文档

快速上手 快速上手 — Requests 2.18.1 文档

基本使用
import requests
url = 'http://www.baidu.com'
response = requests.get(url=url)
#一个类型和六个属性
#Response类型
print(type(response))
#设置响应的编码格式
response.encoding = 'utf-8'
#以字符串的形式返回网页源码
print(response.text)
#返回一个url地址
print(response.url)
#返回二进制数据
print(response.content)
#返回响应状态码
print(response.status_code)
#返回响应头
print(response.headers)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
requests的get请求

参数使用params传递

参数无需urlencode编码

不需要请求对象的定制

请求资源路劲中?可以不加

import requests
url = 'http://www.baidu.com/s'
headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
'Cookie': 'BIDUPSID=D043207FA0BA8EDA6DE237D13B7A2085; PSTM=1679819122; BAIDUID=D043207FA0BA8EDA6B95F9AF636CC568:FG=1; BAIDUID_BFESS=D043207FA0BA8EDA6B95F9AF636CC568:FG=1; ZFY=SRkQXXk5q963dsWp6MbBx:A9BVsfItJEu2v0jm:BIARX0:C; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_PS_PSSID=38515_36561_38470_38468_38375_37936_38387_38356_26350; BA_HECTOR=200k85012hag2kag808h24dm1i3nmlg1n; PSINO=6; delPer=0; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BCLID=8184894944099422743; BCLID_BFESS=8184894944099422743; BDSFRCVID=EKtOJexroG07VWbfMcMcMWLvdFweG7bTDYrEOwXPsp3LGJLVFe3JEG0Pts1-dEu-S2OOogKKLgOTHUCF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; BDSFRCVID_BFESS=EKtOJexroG07VWbfMcMcMWLvdFweG7bTDYrEOwXPsp3LGJLVFe3JEG0Pts1-dEu-S2OOogKKLgOTHUCF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tRAOoC_-tDvDqTrP-trf5DCShUFs0xnJB2Q-XPoO3KtbSx3PbxcjXttI3PvqKU5f5mkf3fbgy4op8P3y0bb2DUA1y4vp0tLeWeTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPb9QgbP5hQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHj8WDj5b3O; H_BDCLCKID_SF_BFESS=tRAOoC_-tDvDqTrP-trf5DCShUFs0xnJB2Q-XPoO3KtbSx3PbxcjXttI3PvqKU5f5mkf3fbgy4op8P3y0bb2DUA1y4vp0tLeWeTxoUJ2-KDVeh5Gqq-KXU4ebPRiWPb9QgbP5hQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHj8WDj5b3O; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1680340062,1681644218; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1681644271; ab_sr=1.0.1_ODQ3MWVjOTRjMmNhZjlmMzdlZGExZDUzNjZjNzBjZjVkOTIwOTE0MTVmNzg2NDVmMWM5YTc1MTQxMWMxYTMyODgzNDhjODQyMzZlNjZiYmE1Mjg2YTBhZGE4NGNhNTVlN2Y4Y2ExNzNkYjBkZjM3MGYxMTIwMDk0NDFkNzBiMzdkZjJiODFkZTlmNWJmMWE4ODQ5ZjE5ZDRjMmJlODRhNQ=='
    }
data = {
    'wd':'北京'
}
#url请求资源路径  params参数  kwargs字典
response = requests.get(url=url,params=data,headers=headers)
response.encoding = 'utf-8'
content = response.text
print(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
requests的post请求

post请求不需要编解码

post请求参数是data

不需要请求对象的定制

import requests
url = 'https://fanyi.baidu.com/sug'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}
data = {
    'kw':'eye'
}
response = requests.post(url=url,data=data,headers=headers)
content = response.text
import json
obj = json.loads(content)
print(obj)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
requests代理
import requests
url = 'http://www.baidu.com/s?'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
    
    }
data = {
    'wd':'ip'
}
#代理的ip
proxy = {
    'http':'60.167.20.156:1133'
}
response = requests.get(url=url,headers=headers,params=data,proxies=proxy)
response.encoding = 'utf-8'
content = response.text
with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
requests的cookie登录 古诗文网
#通过登录 进入到主页面
#通过登陆接口发现 登录的时候需要的参数很多
# __VIEWSTATE: CP3QIJUj3fNNIMyAbBfpI+sp27YaeFH9BAe8qKi8JPdvSus4hqUknovahzQOhH5mAC+Z2cQZ8XESxKjvBC19ufH9dBIjEV1ezk3LHvHkiAMKF3NLdZmW86c4D7DDjqiiY4y3/lkVY86V7w09qbcEI97FfcE=
# __VIEWSTATEGENERATOR: C93BE1AE
# from: http://so.gushiwen.cn/user/collect.aspx
# email: 17609092650
# pwd: 122456
# code: ey2l
# denglu: 登录
#观察到__VIEWSTATE、__VIEWSTATEGENERATOR、code是变量
#难点(1)隐藏域__VIEWSTATE __VIEWSTATEGENERATOR  一般情况下看不到的数据都在页面源码中
# 观察到两个数据在页面源码 所以需要获取页面源码 然后进行解析就可以获取了
#    (2)验证码

import requests
#登录页面的url地址
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}
#获取页面源码
response = requests.get(url=url,headers=headers)
content = response.text

#解析页面源码 然后获取__VIEWSTATE、__VIEWSTATEGENERATOR
from bs4 import BeautifulSoup

soup = BeautifulSoup(content,'lxml')
#获取__VIEWSTATE
viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value')
#获取__VIEWSTATEGENERATOR
viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')

#获取验证码图片
code = soup.select('#imgCode')[0].attrs.get('src')
code_url = 'https://so.gushiwen.cn' + code

#requests里有一个方法session()通过session的返回值 就能使用请求变成一个对象
session = requests.session()
#验证码的url的内容
response_code = session.get(code_url)
#注意此时要用二进制 因为我们要使用的是图片下载
content_code = response_code.content
#wb模式将二进制数据写入文件
with open('code.jpg','wb')as fp:
    fp.write(content_code)

#获取验证码图片后 下载到本地 然后观察验证码 输入到控制台 给code就可以登录
code_name = input('请输入你的验证码')

#点击登录
url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data_post = {
    '__VIEWSTATE': viewstate,
    '__VIEWSTATEGENERATOR': viewstategenerator,
    'from': 'http://so.gushiwen.cn/user/collect.aspx',
    'email': '17609092650',
    'pwd': 'abc8891999',
    'code': code_name,
    'denglu': '登录'
}
response_post = session.post(url=url,headers=headers,data=data_post)
content_post = response_post.text
with open('gushiwen.html','w',encoding='utf-8') as fp:
    fp.write(content_post)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
05.scrapy
配置环境
1.创建爬虫项目 scrapy startproject 项目的名字
            注意:项目的名字不允许使用数字开头  也不能包含中文
2.创建爬虫文件
            (1)要在spiders文件夹中创建爬虫文件
            cd 项目名字\项目名字\spiders
            cd scrapy_baidu_091\scrapy_baidu_091\spiders

            (2)创建爬虫文件
            scrapy genspider 爬虫文件的名字 要爬取网页
            eg:scrapy genspider baidu http://www.baidu.com
            一般情况下不需要添加http协议  因为start——urls的值是根据			allowed_domains修改的  所以添加了http的话 start_urls 				就需要我们手动去修改了
3.运行爬虫代码
            settings里的ROBOTSTXT_OBEY = True要注释掉
            注释掉就不遵守robots协议了  君子协议
            运行爬虫:
            scrapy crawl 爬虫的名字
            eg:scrapy crawl baidu
            
tips:去掉无关日志信息LOG_LEVEL='ERROR'   setting里
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
框架讲解
import scrapy


class BaiduSpider(scrapy.Spider):
    #爬虫的名字  用于运行爬虫的时候 使用的值
    name = "baidu"
    
    #允许访问的域名
    allowed_domains = ["http://baidu.com"]
    
    #起始的url地址  第一次要访问的域名
    #start_urls 是在allowed_domains的前面添加一个http://
    #            在allowed_domains后面加/
    start_urls = ["https://baidu.com"]
    
    #执行了start_urls之后 执行的方法 方法中response就是返回的那个对象
    #相当于 response = urllib.requests.urlopen()
    #       response = response.get()
    def parse(self, response):
        #代码
        print('我是谁')
        
#tips   如果连接进去无数据就是xpath路径问题
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
项目的结构

项目名字

​ 项目名字

​ spiders文件夹(存储的是爬虫文件)

​ init

​ 自定义的爬虫文件 核心功能文件 ********

​ init

​ items 定义数据结构的地方 爬取的数据包含哪些

​ middleware 中间件 代理

​ pipelines 管道 用来处理下载的数据

​ settings 配置文件 robots协议 ua定义等

response的属性和方法

response.text 获取的是响应的字符串

response.body 获取的是二进制数据

response.xpath 可以直接是xpath方法来解析response中的内容

response.extract( ) 提取seletor对象的data属性值

response.extract_first( ) 提取的seletor列表的第一个数据

架构组成

请添加图片描述

工作原理

请添加图片描述

scrapy shell交互终端

Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取 数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。 该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该 终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。 一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。

进入到scrapy shell的终端 直接在windows的终端中输入scrapy shell 域名

scrapy shell www.baidu.com

scrapy当当网爬取数据

yield语句

  1. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代
  2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代 时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
  3. 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始

自定义程序

import scrapy
from ..items import ScrapyDangdang95Item


class DangSpider(scrapy.Spider):
    name = "dang"
    allowed_domains = ["category.dangdang.com"]
    start_urls = ["http://category.dangdang.com/cp01.41.70.01.01.00.html"]

    #多页爬虫
    base_url = 'http://category.dangdang.com/pg'
    page = 1

    def parse(self, response):
        pass
#       src= //ul[@id="component_59"]/li//img/@src
#       alt= //ul[@id="component_59"]/li//img/@alt
#       price=//ul[@id="component_59"]/li//span[@class="search_now_price"]/text()
#       所有的seletor对象 都可以再次调用xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')
        for li in li_list:
            src = li.xpath('.//img/@data-original').extract_first()
            #第一张没有懒加载 和其他图片的标签属性是不一样的
            if src:
                src = src
            else:
                src = li.xpath('.//img/@src').extract_first()

            name = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//span[@class="search_now_price"]/text()').extract_first()

            book = ScrapyDangdang95Item(src=src,name=name,price=price)

            #获取一个book就将book交给pipelines  返回单个对象
            yield book

#每一页爬取的逻辑全是一样的  我们只需要将执行的那个页的请求再次调用parse方法
        if self.page < 100:
            self.page = self.page + 1

            url = self.base_url + str(self.page) + '-cp01.41.70.01.01.00.html'

            #怎么调用parse方法
            #就是scrapy的get请求
            #url就是请求地址 callback就是你要执行的那个函数  注意不加()
            yield scrapy.Request(url=url,callback=self.parse)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

items数据结构

import scrapy

class ScrapyDangdang95Item(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    #通俗的说你要下载的数据都有什么
    src = scrapy.Field()
    name = scrapy.Field()
    price = scrapy.Field()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

pipelines管道

#如果想使用管道的话 那么就必须在settings开启
class ScrapyDangdang95Pipeline:
    #在爬虫文件开始之前就执行的方法
    def open_spider(self,spider):
        self.fp = open('book.json','w',encoding='utf-8')

    #item就是yield后面的book对象
    def process_item(self, item, spider):
        #以下这种模式不推荐   每传递过来一个对象 就打开一次文件 对文件的			操作过于频繁
        #(1)write 方法必须要是一个字符串 而不能是其他对象
        # with open('book.json','a',encoding='utf-8') as fp:
        #     fp.write(str(item))

        self.fp.write(str(item))
        return item

    #在爬虫文件执行之后 执行的方法
    def close_spider(self,spider):
        self.fp.close()

import urllib.request
#多条管道同时开启
#   (1)定义管道类
#   (2)在settings中开启管道
#   "scrapy_dangdang_95.pipelines.DangDangDownloadPipeline":400
class DangDangDownloadPipeline:
    def process_item(self, item, spider):

        url = 'http:'+ item.get('src')
        filename = './books/'+str(item.get('name'))+'.jpg'

        urllib.request.urlretrieve(url=url,filename=filename)
        return item
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
'
运行
多级爬取(meta传递)
import scrapy

from ..items import ScrapyMovie99Item


class MvSpider(scrapy.Spider):
    name = "mv"
    allowed_domains = ["www.dygod.net"]
    start_urls = ["http://www.dygod.net/html/tv/rihantv/index.html"]

#    要第一页的名字 和 第二页的图片
    def parse(self, response):
        a_list = response.xpath('//ul//a[@class="ulink"]')

        for a in a_list:
            #获取第一页的name 和 要跳转的链接
            name = a.xpath('./text()')
            href = a.xpath('./@href').extract_first()


            #第二页的地址是
            url = 'https://www.dygod.net/' + href

            #对第二页链接发起访问
            yield scrapy.Request(url=url,callback=self.parse_second,meta={'name':name})

    def parse_second(self,response):
        src = response.xpath('//div[@id="Zoom"]/img/@src').extract_first()
        #接受到请求的那个meta参数的值
        name = response.meta['name']

        movie = ScrapyMovie99Item(src=src,name=name)

        yield movie
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
crawlspider

CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发 送请求

所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常合适的

日志信息

日志级别:

​ CRITICAL:严重错误

​ ERROR: 一般错误

​ WARNING: 警告

​ INFO: 一般信息

​ DEBUG: 调试信息

默认的日志等级是DEBUG 只要出现了DEBUG或者DEBUG以上等级的日志 那么这些日志将会打印

#指定日志级别
LOG_LEVEL = 'WARING'
#日志文件存储在logdemo.log的文件中
LOG_FILE = 'logdemo.log'
  • 1
  • 2
  • 3
  • 4
'
运行
scrapy的post请求
class Tset(scrapy.Spider):
    name = 'testpost'
    allowed_domains = ['https://fanyi.baidu.com/sug']
    #post请求 没有参数就无意义
    #start_urls 和 parse 都没用了
    def start_requests(self):
        url = 'https://fanyi.baidu.com/sug'
        data = {
            'kw':'final'
        }
        yield scrapy.FormRequest(url=url,formdata=data,
                                 callback=self.parse_second)
     def parse_second(self,response):
        content = response.text
        obj = json.loads(content,encoding='utf-8')
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
代理
1)到settings.py中,打开一个选项
	DOWNLOADER_MIDDLEWARES = {
		'postproject.middlewares.Proxy': 543,
	}2)到middlewares.py中写代码
	def process_request(self, request, spider):
		request.meta['proxy'] = 'https://113.68.202.10:9999'
		return Non
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
06.Python基础

爬虫环境配置与python基础语法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/813793
推荐阅读
相关标签
  

闽ICP备14008679号