request模块

request模块

  - urllib模块

  - requests模块

requests模块:

  python中原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高.

作用:

  模拟浏览器发请求

如何使用:

  - 指定url

  - 发起请求

  - 获取响应数据

  - 持久化存储

第一章: request模块

1. 爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)  get请求  text文本

  - UA检测

  - UA伪装

import requests
if __name__ == '__main__':
    # 1. 指定URL
    url = 'https://www.sogou.com/web'
    # UA伪装
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
    }
    # 搜索关键字
    kw = input('enter a word:')
    param = {
        'query': kw,
    }

    # 2. 发起请求
    response = requests.get(url=url, params=param, headers=headers)

    # 3. 获取响应数据
    page_text = response.text

    # 4. 持久化存储
    fileName = kw + '.html'
    with open(fileName, 'w', encoding='utf-8') as fp:
        fp.write(page_text)

    print(fileName, '保存成功!')
View Code

 2. 破解百度翻译  post请求  json()对象数据

  - post请求(携带了参数)

  - 响应数据是一组json数据

import requests
import json
if __name__ == '__main__':
    # 1. 指定url
    post_url = "https://fanyi.baidu.com/sug"
    # 2. 进行UA伪装
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
    }
    # 3. post请求参数处理(同get请求一致)
    kw = input('enter a word:')
    data = {
        'kw': kw
    }
    # 4. 请求发送
    response = requests.post(url=post_url, data=data, headers=headers)
    # 5. 获取响应数据: json()方法返回的是obj, 如果确认响应数据是json类型的,才可以使用json()
    dic_obj = response.json()
    # 6. 持久化存储
    fileName = kw + '.json'
    fp = open(fileName, 'w', encoding='utf-8')
    json.dump(dic_obj, fp=fp, ensure_ascii=False)  # 数据中包含中文,但中文不能用ascii码编码,所以这里增加参数ensure_ascii=False
    print('over!')
View Code

 3. 爬取豆瓣电影分类排行榜  get请求  json()对象数据

import requests
import json
if __name__ == '__main__':
    url = 'https://movie.douban.com/j/chart/top_list'
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
    }

    param = {
        "type": "24",
        "interval_id": "100:90",
        "action": "",
        "start": "0",  # 从库中第几部开始取
        "limit": "20"  # 一次取出的个数
    }
    response = requests.get(url=url, params=param, headers=headers)
    list_data = response.json()
    fp = open('./douban.json', 'w', encoding='utf-8')
    json.dump(list_data, fp=fp, ensure_ascii=False)

    print('over!!!')
View Code

 4. 爬取肯德基餐厅信息  post请求  text文本

  - post请求url要写完整

import requests

if __name__ == '__main__':
    # 1. url
    post_url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword"
    # 2. UA伪装
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
    }
    # 3. 携带数据
    city = input('enter a city:')
    data = {
        "cname": "",
        "pid": "",
        "keyword": city,
        "pageIndex": "1",
        "pageSize": "10"
    }

    # 4. 发起请求
    response = requests.post(url=post_url, data=data, headers=headers)

    # 5. 获取数据
    restaurants = response.text

    # 6. 持久化
    print(restaurants)
    fileName = city + '.html'
    with open(fileName, 'w', encoding='utf-8') as fp:
        fp.write(restaurants)
View Code

5. 爬取药监总局化妆品登记信息  post请求  json()对象

import requests


if __name__ == '__main__':
    url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'

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

    data = {
        'on': 'true',
        'page': '1',
        'pageSize': '15',
        'productName': '',
        'conditionType': '1',
        'applyname': "",
        'applysn': ''
    }

    res_json = requests.post(url=url, headers=headers, data=data).json()

    print(res_json['list'])

    # [{'ID': 'ed59438f34ae47e794f4c7ee5137c1f7', 'EPS_NAME': '海南京润珍珠生物技术股份有限公司', 'PRODUCT_SN': '琼妆20160001', 'CITY_CODE': '311', 'XK_COMPLETE_DATE': {'date': 25, 'day': 0, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1619280000000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-25', 'QF_MANAGER_NAME': '海南省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91460000294121210Y', 'XC_DATE': '2021-04-25', 'NUM_': 1}, {'ID': '9fc761a8ec9c4d98ae1c8fa8889d23a4', 'EPS_NAME': '云南世纪华宝医药产业开发有限公司', 'PRODUCT_SN': '云妆20190003', 'CITY_CODE': '206', 'XK_COMPLETE_DATE': {'date': 21, 'day': 3, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618934400000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2024-09-30', 'QF_MANAGER_NAME': '云南省食品药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '915323000804056728', 'XC_DATE': '2021-04-21', 'NUM_': 2}, {'ID': '5eb10afc74a2462c8e86652ec8d90a48', 'EPS_NAME': '无锡邦士立生物科技有限公司', 'PRODUCT_SN': '苏妆20160013', 'CITY_CODE': '82', 'XK_COMPLETE_DATE': {'date': 20, 'day': 2, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618848000000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-20', 'QF_MANAGER_NAME': '江苏省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91320213355032183D', 'XC_DATE': '2021-04-20', 'NUM_': 3}, {'ID': 'a2cf9eca47f742a6ba59c945a9c1ce50', 'EPS_NAME': '惠州市新俊雅礼品有限公司', 'PRODUCT_SN': '粤妆20210116', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-18', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91441302MA4UKKYU7H', 'XC_DATE': '2021-04-19', 'NUM_': 4}, {'ID': 'bc36d30f81da4130bd2696c691f44893', 'EPS_NAME': '广州启迪生物科技有限公司', 'PRODUCT_SN': '粤妆20210115', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-18', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA9W1FJQ2Y', 'XC_DATE': '2021-04-19', 'NUM_': 5}, {'ID': '80c32a082b3d400da55afe838ded7e31', 'EPS_NAME': '广东同仁堂科技有限公司', 'PRODUCT_SN': '粤妆20210114', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-18', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA9UT56R1F', 'XC_DATE': '2021-04-19', 'NUM_': 6}, {'ID': '369682cefc0942e9a820e09ad8223b4c', 'EPS_NAME': '广州常青藤化妆品有限公司', 'PRODUCT_SN': '粤妆20210113', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-18', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '9144011179940374XH', 'XC_DATE': '2021-04-19', 'NUM_': 7}, {'ID': '31014906fe134a36b9a34006d816371e', 'EPS_NAME': '汕头市正美日化有限公司', 'PRODUCT_SN': '粤妆20210110', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-04-18', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440514MA54Y20M0T', 'XC_DATE': '2021-04-19', 'NUM_': 8}, {'ID': '091cdb11f4734b5fbad59bcabdef8a41', 'EPS_NAME': '广州茗莎生物科技有限公司', 'PRODUCT_SN': '粤妆20210077', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2026-03-17', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA9W1QY64P', 'XC_DATE': '2021-04-19', 'NUM_': 9}, {'ID': '5ed3142f85f945efad6404f236c00ab6', 'EPS_NAME': '广州智创智美生物科技有限公司', 'PRODUCT_SN': '粤妆20200103', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2025-07-01', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA5D4JRC1L', 'XC_DATE': '2021-04-19', 'NUM_': 10}, {'ID': 'b6d6dd68a6964915991994e91dc6a462', 'EPS_NAME': '广州市华业化妆品有限公司', 'PRODUCT_SN': '粤妆20170589', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2022-11-16', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA59QLU8XH', 'XC_DATE': '2021-04-19', 'NUM_': 11}, {'ID': '0cc1168d9951479b989fe2639754fd57', 'EPS_NAME': '广州市御象实业有限公司', 'PRODUCT_SN': '粤妆20170374', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2022-04-12', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA59EB967N', 'XC_DATE': '2021-04-19', 'NUM_': 12}, {'ID': '58bc161b2f5e4bcd9d4722e90b1a61e9', 'EPS_NAME': '广州市媚黛生物科技有限公司', 'PRODUCT_SN': '粤妆20170307', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2022-03-02', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA59GR6E8M', 'XC_DATE': '2021-04-19', 'NUM_': 13}, {'ID': '41f6cde894294002ae587193d69796ae', 'EPS_NAME': '广州柏灡化妆品有限公司', 'PRODUCT_SN': '粤妆20170211', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2024-09-02', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440111675650669X', 'XC_DATE': '2021-04-19', 'NUM_': 14}, {'ID': 'e645b1730d3c4fce946f80c87c77a9ee', 'EPS_NAME': '广州合众无纺化妆品集团有限公司', 'PRODUCT_SN': '粤妆20170086', 'CITY_CODE': None, 'XK_COMPLETE_DATE': {'date': 19, 'day': 1, 'hours': 0, 'minutes': 0, 'month': 3, 'nanos': 0, 'seconds': 0, 'time': 1618761600000, 'timezoneOffset': -480, 'year': 121}, 'XK_DATE': '2022-01-15', 'QF_MANAGER_NAME': '广东省药品监督管理局', 'BUSINESS_LICENSE_NUMBER': '91440101MA59EXE93U', 'XC_DATE': '2021-04-19', 'NUM_': 15}]
View Code

 

 第二章:数据解析

  - 数据解析原理:

    - 1. 标签定位

    - 2. 提取标签、标签属性中存储的数据值

1. 爬取单张图片  get请求  content二进制类型数据

import requests
if __name__ == '__main__':
    url = 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1106416652,146193367&fm=26&gp=0.jpg'

    response = requests.get(url=url).content
    with open('./qiutu.jpg', 'wb') as fp:
        fp.write(response)

    print('over!!')
View Code

 2. 正则解析案例:爬取糗图百科的热图栏目所有分页中的所有图片  get请求  text, content数据

  - 使用正则表达式,匹配页面(text文本)中的图片(src属性)地址

import requests
import re
import os

if __name__ == '__main__':
    # 创建一个文件夹,用于存放所有图片
    if not os.path.exists('./qiutu'):
        os.mkdir('./qiutu')

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

    # 循环页码,进行多页爬取
    for pageNum in range(1, 3):  # 这里只演示爬取前两页
        if not os.path.exists(f'./qiutu/{pageNum}'):
            os.mkdir(f'./qiutu/{pageNum}')
        page_url = f'https://www.qiushibaike.com/imgrank/page/{pageNum}/'
        print(page_url)
        # 爬取一页的源代码
        page_text = requests.get(url=page_url, headers=headers).text

        # 提取图片地址的正则表达式,注意()内的就将是提取到的地址
        ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'

        # re.S表示单行匹配, 在数据解析中都是用单行匹配的。
        src_list = re.findall(ex, page_text, re.S)  # 提取出页码中所有的图片地址

        for src in src_list:
            img_name = src.split('/')[-1]  # 取出图片的文件名称
            src = 'https:' + src
            img_path = f'./qiutu/{pageNum}/{img_name}'
            img_data = requests.get(url=src, headers=headers).content
            with open(img_path, 'wb') as fp:
                fp.write(img_data)
            print(img_name, '下载成功!')
    print('over!!')
View Code

 3. bs4进行数据解析

  - bs4数据解析原理:

    - 1. 实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中

    - 2. 通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取

  - 环境安装:

    - pip install bs4

    - pip install lxml  解析器

  - 如何实例化BeautifulSoup对象:

    - from bs4 import BeautifulSoup

    - 对象的实例化:

      - 1. 将本地的htl文档中的数据加载到该对象中

        fp = open('./test.html', 'r', encoding='utf-8')

        soup = BeautifulSoup(fp, 'lxml')

      - 2. 将互联网上获取的页面源码加载到该对象中

        page_text = response.text

        soup = BeautifulSoup(page_text, 'lxml')

    - 提供的用于数据解析的方法和属性:

      - soup.tagName(标签名称): 返回的是html中第一次出现的tagName标签  如: print(soup.div)  print(soup.a)

      - soup.find():

        - soup.find('tagName'): 等同与soup.tagName  如:soup.find('div')

        - 属性定位:

          - soup.find('div', class_='song): 定位到class属性是song的div标签(class属性需要加下划线,其他属性不需要id/attr)

      - soup.find_all('tagName'): 返回符合要求的所有标签(返回值为列表), 和soup.find()一样也可以使用属性进行筛选(定位)

    - soup.select:

      - soup.select('某种选择器(id, class, 标签...选择器)')返回值是列表  如:soup.select('.tang')定位到类属性为class='tang'的所有标签

      - 层级选择器的使用:

        - soup.select('.tang > ul > li > a')[0] : >表示的是一个层级

        - soup.select('.tang > ul a')[0] : 空格表示的是夸多个层级

    - 获取标签之间的文本数据:

      - soup.a.text  soup.a.string  soup.a.get_text()  soup.a.text/string/get_text()

      - text/get_text(): 可以获取标签中的所有文本内容(包含该标签的所有下级标签中的文本)

      - string: 只可以获取该标签下面直系的文本内容(无法获取该标签的子(孙)标签中的文本)

    - 获取标签中属性值:

      - soup.a['href']  如:获取a标签的href值,soup.select('.tang > ul a')[0]['href']
View Code

  - bs4实例:爬取三国演义全部内容

import requests
from bs4 import BeautifulSoup
import time

if __name__ == '__main__':

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
    }
    # 三国演义目录页面url
    title_url = 'https://www.shicimingju.com/book/sanguoyanyi.html'

    title_page_text = requests.get(url=title_url, headers=headers).content  # 这里使用.content而不是用.text,可以防止中文乱码

    soup = BeautifulSoup(title_page_text, 'lxml')

    li_list = soup.select('.book-mulu > ul > li')  # 每一章标题的li标签

    fp = open('./sanguo.txt', 'w', encoding='utf-8')

    for li in li_list:
        time.sleep(2)
        title = li.a.string

        # 三国演义每一个章节详细内容页面url
        detail_url = 'https://www.shicimingju.com' + li.a['href']

        detail_text = requests.get(url=detail_url, headers=headers).content
        detail_soup = BeautifulSoup(detail_text, 'lxml')

        detail_text = detail_soup.find('div', class_='chapter_content').text

        fp.write(title + ':' + detail_text + '\n')
        print(title, '爬取成功!')
View Code

 4. xpath解析: 最常用且最便捷高效的一种解析方式。通用性。

   - xpath解析原理:

    - 1. 实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中.

    - 2. 调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获.

  - 环境安装:

    - pip install lxml

  - 如何实例化一个etree对象: from lxml iport etree

    - 1. 将本地的html文档中的源码数据加载到etree对象中:

      etree.parse(filePath)

    - 2. 可以将从互联网上获取的源码数据加载到该对象中

      etree.HTML('page_text')

    - xpath('xpath表达式')  学习重点

  - xpath表达式:

    - /:表示的是从根节点开始定位.表示的是一个层级.

      - tree = etree.parse('test.thml')  r = tree.xpath('/html/body/div')  返回值是列表,元素时element对象(标签对象)

    - //:表示的是多个层级.可以表示从任意位置开始定位.

      - r = tree.xpath('/thml//div')

      - r = tree.xpath('//div')

    - ./:表示从当前定位到的标签开始

      - r = li.xpath('./div[2]/h2/a')  表示从当前的li标签开始,向其内部层级深入

    - |: 连接xpath内的两个表达式,表示或者关系

      - r = tree.xpath('//div/ul/li | //div/div/p')

    - 属性定位: tagName[@attrName='attrValue']

      - r = tree.xpath('//div[@class="song"]')

    - 索引定位:

      - r = tree.xpath('//div[@class="song"]/p[3]')  索引是从1开始的,定位到第3个p标签

    - 取文本

      - /text()  只能获取直系的文本(无法获取其子孙标签中的文本), 返回值是列表

        - r = tree.xpath('//div[@class="tang"]//li[5]/a/text()')[0]  获取第5个li标签下的a标签中的文本

      - //text() 获取标签中全部文本内容(包含子孙标签中的文本)

        - r = tree.xpath('//li[7]//text()')  获取第7个li标签下的全部文本

    - 取属性值

      - /@attrName  ===>img/@src

        - r = tree.xpath('//div[@class="song"]/img/@src')  获取src的值, 返回值是列表

   - xpath实例,爬取58同城二手房信息

import requests
from lxml import etree
if __name__ == '__main__':

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

    # 爬取到页面源码数据
    url = 'https://siyang.58.com/ershoufang/'
    page_text = requests.get(url=url, headers=headers).text
    # 数据解析
    tree = etree.HTML(page_text)
    # 使用xpath定位出房源标题文本的位置标签
    div_list = tree.xpath('//section[@class="list"]/div[@class="property"]')

    fp = open('58.txt', 'w', encoding='utf-8')  # 数据持久化
    for div in div_list:
        # 提取出标题文本
        title = div.xpath('./a//h3[@class="property-content-title-name"]/text()')[0]
        print(title)
        fp.write(title + '\n')
View Code

   - xpath实例,爬取4K图片

import requests
import os
from lxml import etree
if __name__ == '__main__':
    if not os.path.exists('./美女图片'):
        os.mkdir('./美女图片')
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
    }
    url = 'https://pic.netbian.com/4kmeinv/'

    response = requests.get(url=url, headers=headers)
    # 第一种解中文乱码的方法, 如果不行使用第二种
    # response.encoding = 'utf-8'
    page_text = response.text
    # print(page_text)
    tree = etree.HTML(page_text)
    # 解析定位出图片的位置,在li标签中
    li_list = tree.xpath('//div[@class="slist"]/ul/li')

    for li in li_list:
        # 获取图片的真实地址,获取src属性的值
        img_src = 'https://pic.netbian.com' + li.xpath('./a/img/@src')[0]
        # 获取图片的alt属性值,作为图片的名称
        img_name = li.xpath('./a/img/@alt')[0] + '.jpg'
        # 第二种解中文乱码的方法
        img_name = img_name.encode('iso-8859-1').decode('gbk')
        # 数据持久化
        img_path = '美女图片/' + img_name
        img_data = requests.get(url=img_src, headers=headers).content
        with open(img_path, 'wb') as fp:
            fp.write(img_data)
        print(img_name, '下载成功!')
View Code

  - xpath实例,爬取全国城市名称

 

 

     - 第一处li标签中有热门城市名称

   

    - 第二处li标签中有其他所有城市的名称

    

 

 

import requests
from lxml import etree


if __name__ == '__main__':

    url = 'https://www.aqistudy.cn/historydata/'

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

    page_text = requests.get(url=url, headers=headers).text

    tree = etree.HTML(page_text)

    city_name_list = []
    # 获取热点城市的城市名称
    hot_li_list = tree.xpath('//div[@class="bottom"]/ul/li')
    for hot in hot_li_list:
        hot_city_name = hot.xpath('./a/text()')[0]
        city_name_list.append(hot_city_name)

    # 获取其它全部城市名称
    other_li_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
    for other in other_li_list:
        other_city_name = other.xpath('./a/text()')[0]
        city_name_list.append(other_city_name)

    print(city_name_list, len(city_name_list))
爬取全国城市,方法一
import requests
from lxml import etree


if __name__ == '__main__':

    url = 'https://www.aqistudy.cn/historydata/'

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

    page_text = requests.get(url=url, headers=headers).text

    tree = etree.HTML(page_text)

    city_name_list = []
    # xpath表达式中采用|或者关系符号连接两个标签定位式子
    li_list = tree.xpath('//div[@class="bottom"]/ul/li | //div[@class="bottom"]/ul/div[2]/li')
    for li in li_list:
        city_name = li.xpath('./a/text()')[0]
        city_name_list.append(city_name)

    print(city_name_list, len(city_name_list))
方法二, 采用|或者关系符号

   -xpath爬取实例: 爬取站长素材中的免费简历模板

 

    - 简历列表Div标签位置(简历详情页面的URL)

 

 

    - 简历rar下载地址

 

 

import requests
import os
from lxml import etree
import time
import re

if __name__ == '__main__':
    if not os.path.exists('./简历模板'):
        os.mkdir('./简历模板')
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
    }
    list_url = 'https://sc.chinaz.com/jianli/index.html'

    page_list_text = requests.get(url=list_url, headers=headers).text

    tree = etree.HTML(page_list_text)
    # 模板详情页面的div标签列表
    div_list = tree.xpath('//div[@id="main"]/div/div')

    for div in div_list:
        time.sleep(2)
        # 获取模板详情页面url
        download_page_url = 'https:' + div.xpath('./a/@href')[0]

        response = requests.get(url=download_page_url, headers=headers)
        response.encoding = 'utf-8'  # 解决乱码问题
        download_page_text = response.text
        # print(download_page_text)

        ex = '模板原价'
        is_in = re.findall(ex, download_page_text, re.S)
        # print(is_in)
        if is_in:
            print('付费模块,不爬取!')
            continue

        download_tree = etree.HTML(download_page_text)
        # 模板文件下载地址
        download_file_url = download_tree.xpath('//div[@id="down"]/div[2]/ul/li[4]/a/@href')[0]

        file_name = download_file_url.split('/')[-1]
        # 获取模板文件二进制数据
        file_data = requests.get(url=download_file_url, headers=headers).content
        # 数据持久化
        file_path = '简历模板/' + file_name

        with open(file_path, 'wb') as fp:
            fp.write(file_data)
        print(file_name, '下载完毕!')
View Code

 第三章:验证码识别

1.打码网站:验证码识别网站http://www.chaojiying.com/price.html

超级鹰验证码识别功能的类源代码:

# chaojiying.py

#!/usr/bin/env python
# coding:utf-8

import requests
from hashlib import md5


class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password = password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
                          headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()


if __name__ == '__main__':
    chaojiying = Chaojiying_Client('lldbty', 's666888999', '915545')  # 用户中心>>软件ID 生成一个替换 96001
    im = open('a.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    print(chaojiying.PostPic(im, 1902))  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
View Code

2. 古诗文网站登录的验证码识别代码

import requests
from lxml import etree
from Chaojiying_Python.chaojiying import Chaojiying_Client  # 调用验证码识别模块 超级鹰

if __name__ == '__main__':
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
    }
    login_page_url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
    # 获取登录页面中的验证码图片,下载到本地
    login_page_text = requests.get(url=login_page_url, headers=headers).text
    tree = etree.HTML(login_page_text)
    code_img_url = 'https://so.gushiwen.org/' + tree.xpath('//*[@id="imgCode"]/@src')[0]
    code_img_data = requests.get(url=code_img_url, headers=headers).content
    with open('code.jpg', 'wb') as fp:
        fp.write(code_img_data)
    # 使用超级鹰验证码识别模块识别验证码
    chaojiying = Chaojiying_Client('lldbty', 's666888999', '915545')  # 用户中心>>软件ID 生成一个替换 96001
    im = open('code.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    print(chaojiying.PostPic(im, 1902))  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    # return {'err_no': 0, 'err_str': 'OK', 'pic_id': '1138514226096700002', 'pic_str': 'aes4', 'md5': '80ba2eaeffb49252bcfa29e813e88af6'}
View Code

 第四章:requests模块高级操作  模拟登录  cookie  session

 模拟登录:

  - 爬取基于某些用户的用户信息

需求: 对人人网进行模拟登录

  - 点击登录按钮之后会发起一个post请求

  - post请求中会携带登录之前录入的相关的登录信息(用户名,密码, 验证码......)

  - 验证码:每次请求都会变化

需求:爬取当前用户的相关的用户信息(个人主页中显示的用户信息)

http/https协议特性:无状态

没有请求到对应页面数据的原因:

  发起的第二次基于个人主页页面请求的时候,服务器端并不制定该请求是基于登录状态下的请求。

cookie:用来让服务器端记录客户端的相关状态。

  - 手动处理:通过抓包工具获取cookie值,将该值封装到hearders中。(不建议)

  - 自动处理:

    - cookie值的来源是哪里?

      - 模拟登录post请求后,由服务器端创建。

    session回话对象:

      - 作用:

        1. 可以进行请求的发送

        2. 如果请求过程中产生了cookie,则该cookie会被自动存储/携带在该session对像中。    

    - 创建一个session对象: session = requests.Session()

    - 使用session对象进行模拟登录post请求的发送(cookie就会被存储在session中)

    - session对象对个人主页对应的get请求进行发送(携带了cookie)

需求:request模拟登录某管理系统,并执行查询操作。

import requests
from lxml import etree
from chaojiying import Chaojiying_Client

if __name__ == '__main__':
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
    }
    # 获取验证码字符串
    login_page_url = 'https://xjgl.jse.edu.cn/uids/index.jsp'
    login_page_text = requests.get(url=login_page_url, headers=headers).text
    tree = etree.HTML(login_page_text)
    code_src = 'https://xjgl.jse.edu.cn/uids/' + tree.xpath('//*[@id="imgCode"]/@src')[0]
    code_data = requests.get(url=code_src, headers=headers).content
    with open('./xjcode.jpg', 'wb') as fp:
        fp.write(code_data)
    chaojiying = Chaojiying_Client('lldbty', 's666888999', '915545')  # 用户中心>>软件ID 生成一个替换 96001
    im = open('./xjcode.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    # print(chaojiying.PostPic(im, 1902))  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    code_str = chaojiying.PostPic(im, 1902)['pic_str']
    print(code_str)
    # 携带验证码数据进行第一次模拟登录(302重定向)
    session = requests.Session()
    login_post_url = 'https://xjgl.jse.edu.cn/uids/login.jsp'
    data = {
        "randomCode": code_str,
        "returnURL": "",
        "appId": "uids",
        "encrypt": "1",
        "reqId": "1618915650544",
        "req": "932AAC3E2807596F23E3DA6CC63FDFF649C5F34433A4153F0B4E3FEE71072865CD2D22E33035370D505F516906C0B20024E68C51013390C22424F7DB26B1EC2F",
    }
    response = session.post(url=login_post_url, headers=headers, data=data)
    print('login第一次', response.status_code)  # 获取状态码302
    # 携带用户名密码第二次登录
    index_page_url = 'https://xjgl.jse.edu.cn/studman3/index.jsp'
    data = {
        'ssoLoginName': 'x32132221015',
        'timeStamp': '1618915653187',
        'requestToken': 'baf4a7492956a6aa7ff12c560cf3f625',
        'requestToken2': 'c1e916121580a6dd3cb0bad8dd9b073c'
    }
    response2 = session.post(url=index_page_url, headers=headers, data=data)
    print('login第二次', response2.status_code)

    # 获取学生列表数据
    stu_page_url = 'https://xjgl.jse.edu.cn/studman3/studman/student/studentBrowseAct!list.action?statusCheckBox=0&statusCheckBox=-2&statusCheckBox=1&statusCheckBox=2&statusCheckBox=4&statusCheckBox=5&statusCheckBox=7&statusCheckBox=9&statusCheckBox=10'
    # stu_page_response = session.get(url=stu_page_url, headers=headers)
    # stu_page_response.encoding = 'GBK'
    # stu_page_text = stu_page_response.text
    #
    # with open('./stu_list.html', 'w', encoding='GBK') as fp:
    #     fp.write(stu_page_text)

    # 用姓名检索制定的学生s
    stu_name = input('请输入需要检索的学生姓名:').encode('GBK')
    param = {
        "studentForm.name": stu_name,
        # 'statusCheckBox': '0',
        # 'statusCheckBox': '-2',
        # 'statusCheckBox': '1',
        # 'statusCheckBox': '2',
        # 'statusCheckBox': '4',
        # 'statusCheckBox': '5',
        # 'statusCheckBox': '7',
        # 'statusCheckBox': '9',
        # 'statusCheckBox': '10'
    }
    stu_page_response = session.get(url=stu_page_url, headers=headers, params=param)
    stu_page_response.encoding = 'GBK'
    stu_page_text = stu_page_response.text
    with open('./stu_list.html', 'w', encoding='GBK') as fp:
        fp.write(stu_page_text)
View Code

 

代理: 破解封IP这种反扒机制

什么是代理:

  - 代理服务器

代理的作用:

  - 突破自身IP访问的限制

  - 隐藏自身真实IP

代理相关的网站:

  - 快代理

  - 西祠代理

  - www.goubanjia.com  

代理IP的匿名度:

  - 透明: 服务器知道该次请求使用了代理,也知道请求对应的真实ip

  - 匿名: 知道使用了代理,不知道真实ip

  - 高匿: 不知道使用了代理,更不知道真实的ip

代理ip使用范例:

import requests
from lxml import etree


if __name__ == '__main__':

    url = 'https://www.baidu.com/s?ie=UTF-8&wd=ip'

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

    proxies = {
        "https": "171.35.167.75:9999"
    }
    page_text = requests.get(url=url, headers=headers, proxies=proxies).text
    with open('./ip.html', 'w', encoding='utf-8') as fp:
        fp.write(page_text)
View Code

 

        

posted @ 2021-03-30 20:04  蓝蓝的白云天!  阅读(193)  评论(0编辑  收藏  举报