一周内容回顾(9.27-9.30)

day01

  • 解析库之X-path解析器

  • 实战案例之爬取猪八戒数据

 

X-path解析器

效率很高,使用广泛

模拟网页内容

View Code

导入模块生成对象

# 导入xpath所在模块
from lxml import etree

# 将待匹配的文本传入etree生成一个对象
html = etree.HTML(doc)

主要功能

a = html.xpath('//*')  # 匹配所有的标签
a = html.xpath('//head')  # 匹配所有的head标签
a = html.xpath('//div/a')  # 匹配div标签内部所有的儿子a标签
a = html.xpath('//body//a')  # 匹配div标签内容所有的后代a标签
a=html.xpath('//body//a[@href="image1.html"]')  
# 属性查找 获取body内部所有的href=image1.html后代a
a = html.xpath('//body//a[@href="image1.html"]/..')  
# ..表示查找上一级父标签
'''xpath选择器中中括号内部可以放属性也可以放位置数 从1开始'''
a = html.xpath('//body//a[1]') 

 查找父标签另外一种形式

a = html.xpath('//body//a[1]/parent::*')

 

文本获取

获取某个标签内的文本

a = html.xpath('//body//a[@href="image1.html"]/text()')

获取body内部所有后代a内部文本(一次性获取不需要循环)

a = html.xpath('//body//a/text()')

 属性获取

获取body内部所有后代a标签href属性值

a = html.xpath('//body//a/@href')

获取title标签id属性值

a = html.xpath('//title/@id')
a = html.xpath('//body//a[2]/@href')

 属性多值匹配

a=html.xpath('//body//a[@class="li"]')  # 写等号就表示等于,不是包含
a标签有多个class类,直接匹配就不可以了,需要用contains
a = html.xpath('//body//a[contains(@class,"li")]/text()') 

 

 多属性匹配

a = html.xpath('//body//a[contains(@class,"li") or @name="items"]')

# 查找body标签内部所有class含有li或者name=items的a标签

# 同理可得

# 查找body标签内部所有class含有li并且name=items的a标签的内部文本
a = html.xpath('//body//a[contains(@class,"li") and @name="items"]/text()')

 

 按序选择

取最后一个

a = html.xpath('//a[last()]/@href')

 位置小于3的

# 关键字position()  用于定位
a = html.xpath('//a[position()<3]/@href')  

 倒数第三个

a = html.xpath('//a[last()-2]/@href')

 

X-path爬取猪八戒数据

完整代码

import requests
from bs4 import BeautifulSoup
from lxml import etree
from openpyxl import Workbook

wb = Workbook()
# 构造工作簿
wb1 = wb.create_sheet('猪八戒',0)
# 创建表头
wb1.append(['价格','公司','接单数','详细信息'])

res = requests.get('https://shanghai.zbj.com/search/f/',
                   params={'kw': 'python'}
                   )
x_html = etree.HTML(res.text)
# 查找所有的外部div标签
div_list = x_html.xpath('/html/body/div[6]/div/div/div[2]/div[5]/div[1]/div')  # 利用浏览器自动生成
# 循环获取每一个div标签
for div in div_list:
    price = div.xpath('.//span[@class="price"]/text()')  # 价格
    company_name = div.xpath('./div/div/a[1]/div[1]/p/text()')  # 公司
    order_num = div.xpath('./div/div/a[2]/div[2]/div[1]/span[2]/text()')  # 接单数
    info = div.xpath('./div/div/a[2]/div[2]/div[2]/p/text()')  # 详细信息

    try:
        name = company_name[1].strip('\\n')
    except Exception as f:
        name = ''
    try:
        wb1.append([price[0], name, order_num[0], info[0]])
    except Exception as f:
        continue
# 保存文件
wb.save('猪八戒.xlsx')
View Code

 

day02

  • 爬取城市名称
  • 爬取猪八戒数据并写入表格
  • 爬取贴吧图片数据
  • 自动化测试工具selenuim模块

爬取城市名称

思路

1.向网页发送请求并携带请求头User-Agent参数
2.生成一个xpath对象并研究标签规律
3.利用xpath选择所需数据
4.打印结果

完整代码

View Code

 

爬取猪八戒数据并写入表格

思路

1.朝网页发送get请求
2.生成xpath对象
3.研究标签规律,利用xpath模块筛选
4.先查找所有含有数据的div之后依次循环
5.利用解析器xpath筛选所需数据
6.导入openpyxl模块创建表格
7.定义表头以及写入数据最后保存文件

 完整代码

import requests
from lxml import etree
from openpyxl import Workbook

wb = Workbook()
wb1 = wb.create_sheet('订单数据', 0)
wb1.append(['公司名称', '公司地址', '订单价格', '历史成交', '订单描述'])

# 1.发送请求获取页面数据
res = requests.get('https://shanghai.zbj.com/search/f/',
                   params={'kw': 'app'}
                   )
# 2.生成xpath对象
tree = etree.HTML(res.text)
# 3.研究标签规律 书写xpath
div_list = tree.xpath('//div[@class="new-service-wrap"]/div')
for div in div_list:
    # 公司名称
    company_name = div.xpath('./div/div/a/div[1]/p/text()')
    if not company_name:
        continue
    # print(company_name[-1].strip('\n'))
    # 公司地址
    address_info = div.xpath('./div/div/a/div[1]/div/span/text()')
    # print(address_info[0])
    # 订单价格
    order_price = div.xpath('./div/div/a[2]/div[2]/div[1]/span[1]/text()')
    # print(order_price[0])
    # 历史成交
    order_num = div.xpath('./div/div/a[2]/div[2]/div[1]/span[2]/text()')
    # print(order_num[0])
    # 订单描述
    order_desc = div.xpath('./div/div/a[2]/div[2]/div[2]/p/text()')
    # print('app'.join(order_desc))

    wb1.append([company_name[-1].strip('\n'), address_info[0], order_price[0], order_num[0], 'app'.join(order_desc)])

wb.save(r'订单数据.xlsx')
View Code

 

爬取贴吧图片数据

 需求

贴吧名称是用户自己指定 不是固定的一个
在编写程序的时候可以先以固定的为例之后换成用户输入即可
所有的图片都需要自动保存到以贴吧名称命名的文件夹内
贴吧图片支持多页爬取

思路

1.向网页发送get请求
2.生成一个xpath对象
3.查找所有帖子的链接地址
4.循环获取每一个帖子链接 拼接成完整的地址 再发送请求
5.发送详情页请求获取页面数据
6.筛选图片链接地址
7.循环请求每个图片地址并保存图片

 完整代码

import requests
from lxml import etree
import os
import time

name = input('请输入想要爬取的贴吧名>>>:').strip()
if not os.path.exists(name):
    os.mkdir(name)
page_str = input('请输入你要爬取的代码页数>>>:').strip()
page = (int(page_str) - 1) * 50
res = requests.get('https://tieba.baidu.com/f',
                   params={'kw': name,
                           'pn': page}
                   )  # 通过额外参数控制贴吧和页数
# print(res.text)
tree = etree.HTML(res.text)
second_link_list = tree.xpath('//a[@class="j_th_tit "]/@href')  # 筛选出所有帖子的链接部分
base_url = 'https://tieba.baidu.com'
for link in second_link_list:
    url = base_url + link  # 拿到一个个帖子的链接之后拼接获取完整网址
    res1 = requests.get(url)  # 访问一个个帖子的网址
    tree1 = etree.HTML(res1.text)
    img_link_list = tree1.xpath('//img[@class="BDE_Image"]/@src')  # 筛选出帖子里图片的链接部分
    for img_link in img_link_list:
        res2 = requests.get(img_link)  # 访问一个个图片的网址
        file_path = os.path.join(name, img_link[-10:])  # 起名从后往前拿保证拿到.jpg
        with open(file_path, 'wb') as f:
            f.write(res2.content)  # 写入保存
            time.sleep(1)
View Code

 

 selenium模块

原本仅仅是测试领域里面的一款测试工具 
但是由于其可以操作浏览器所以逐步也被应用到了爬虫领域
可以避免很多防爬措施但是由于需要操控浏览器所以效率上偏慢

 驱动下载

该模块是用来操作浏览器的 需要相应的驱动软件

 注意事项

# 1.有时候下载了驱动可能也无法操作浏览器
        原因:可能是因为驱动版本不对
        措施:重新下一个版本的驱动
# 2.不同的浏览器需要下载不同的驱动文件

驱动文件的存放位置

存放到python解释器scripts文件夹内即可

 基本操作

1、find_element_by_id   根据id找
2、find_element_by_link_text     根据链接名字找到控件(a标签的文字)
3、find_element_by_partial_link_text   根据链接名字找到控件(a标签的文字)模糊查询
4、find_element_by_tag_name       根据标签名
5、find_element_by_class_name     根据类名
6、find_element_by_name           根据属性名
7、find_element_by_css_selector   根据css选择器
8、find_element_by_xpath          根据xpath选择

结论

find_element与find_elements的区别就在于前者只会找到符合条件的第一个,后者是所有
两者的关系相当于bs4模块里面的find与find_all

小案例

from selenium import webdriver
from selenium.webdriver.common.keys import Keys  # 键盘按键操作
import time

bro = webdriver.Chrome()
# 打开淘宝
bro.get('https://www.taobao.com/')
# 查找搜索框标签
input_tag = bro.find_element_by_id('q')
# 输入文本内容
input_tag.send_keys('iphone手机')
time.sleep(1)
# 点击搜索
input_tag.send_keys(Keys.ENTER)
time.sleep(5)
# 关闭浏览器
bro.close()
View Code

 

day03

  • selenuim其他操作

  • 图片验证码与滑动验证码的破解思路

  • 大型复杂爬虫案例讲解

 

selenuim其它操作

获取属性

tag.get_attribute('src')

获取文本内容

tag.text

获取标签ID,位置,名称,大小

print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)

模拟浏览器前进后退

browser.back()
browser.forward()

 cookies管理

browser.get_cookies()  # 获取cookie
browser.add_cookie({'k1':'xxx','k2':'yyy'})  # 设置cookie

运行js

from selenium import webdriver
import time
bro=webdriver.Chrome()
bro.get("http://www.taobao.com")
bro.execute_script('window.scrollTo(0,200)') # 鼠标滚轮移动
time.sleep(5)
View Code

 选项卡管理

print(browser.window_handles)  # 获取所有的选项卡

 

 动作链

方式一

from selenium import webdriver
from selenium.webdriver import ActionChains
import time

driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')

driver.switch_to.frame('iframeResult')  # 必须要指定iframe标签
sourse = driver.find_element_by_id('draggable')
target = driver.find_element_by_id('droppable')
actions = ActionChains(driver)  # 拿到动作链对象
actions.drag_and_drop(sourse, target)  # 把动作放到动作链中,准备串行执行
actions.perform()
View Code

 方式二

from selenium import webdriver
from selenium.webdriver import ActionChains
import time

driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')

driver.switch_to.frame('iframeResult')  # 必须要指定iframe标签
sourse = driver.find_element_by_id('draggable')
target = driver.find_element_by_id('droppable')

actions = ActionChains(driver)
actions.click_and_hold(sourse)
distance = target.location['x'] - sourse.location['x']
track = 0
while track < distance:
    actions.move_by_offset(xoffset=2, yoffset=0).perform()
    track += 5
    time.sleep(0.5)
actions.release()

driver.close()
View Code

 

iframe界面

有时候一个页面上还会叠加其他完整的html页面
该页面一般都是iframe标签 内部含有完整的html文档结构

# 在查找该标签内部的标签时需要指定一个参数
driver.switch_to.frame('iframeResult')

滑动验证码

# 针对滑动验证码也是可以通过selenuim自动完成的

# 滑动验证码很多时候不推荐使用程序破解,太过繁琐
很多时候还不如自己亲自手动滑动来的方便

# 滑动验证码在拖动的时候速度不能太快,内部有监测机制
速度过快一步到位会被认为是爬虫程序

无界面操作

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get('https://www.baidu.com')
print(driver.page_source)
View Code

 

针对selenuim防爬

# 很多程序是可以分辨出来当前浏览器是否被selenuim操作 我们可以在代码中添加如下配置即可避免被识别
from selenium.webdriver import ChromeOptions
option = ChromeOptions()
option.add_experimental_option('excludeSwitchers',['enable-automation'])
driver = webdriver.Chrome(options=option)

 

cookie登录

思路

第一步使用selenium打开网址,然后让用户完成手工登录,再获取cookie
第二步将获取的cookie数据写入文本文件内
第三步获取cookie中的name和value,转化成requests可以使用的形式
第四步使用该cookie完成请求

 

完整代码

import requests
from selenium import webdriver
import time
import json

# 使用selenium打开网址,然后让用户完成手工登录,再获取cookie
# url = 'https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F'
# driver = webdriver.Chrome()
# driver.get(url=url)
# time.sleep(30)  # 预留时间让用户输入用户名和密码
# driver.refresh()  # 刷新页面
# c = driver.get_cookies()  # 获取登录成功之后服务端发返回的cookie数据
# print(c)
# with open('xxx.txt', 'w') as f:
#     json.dump(c, f)

cookies = {}
with open('xxx.txt', 'r') as f:
    di = json.load(f)
# 获取cookie中的name和value,转化成requests可以使用的形式
for cookie in di:
    cookies[cookie['name']] = cookie['value']

# # 使用该cookie完成请求
# response = requests.get(url='https://i-beta.cnblogs.com/api/user', cookies=cookies)
# response.encoding = response.apparent_encoding
# print(response.text)
View Code

 

图片验证码

1.完全使用代码破解

图像识别技术
        软件:Tesseract-ocr 
        模块:pytesseract

 2.打码平台

花钱买第三方服务
先使用代码识别如果不想其实还有一帮员工肉眼识别

3.自己人工智能识别

 

b站视频案例

思路

1.寻找任意一个视频地址
2.分析页面在network中发现该地址发送请求后有两个视频和音频文件比较可疑
研究下来发现b站的视频是一分为二的,分为视频和音频 3.然后用requests模块模拟即可,打开文件不停的发送请求加载数据写入即可

 

红薯网小说案例

思路

1.小说详情页面鼠标左右键全部禁用,但是支持按F12调出控制台
2.研究发现小说文字不是直接加载,于是我们可以查找相关二次请求
3.查找可疑的响应文件,结果发现了两处可疑点,请求体里也有重要参数
4.然后发现文字内容的解密过程发送在浏览器本地,通过浏览器查找相应的js代码,查看该代码内的解密算法
5.怀疑缺失的数据与解析出来js代码有很大的关系,自己新建一个html文件,将content内部拷贝只body内
6.将js代码引入到该html文件夹
7.css反扒破解js注入

 

 

day04

  • 百度自动登录
  • 爬取京东商品数据
  • 知乎登录案例

 

百度自动登录

思路

1.使用谷歌浏览器访问百度首页
2.查找页面上的登录按钮
3.点击登录按钮
4.查找点击短信登录按钮
5.查找手机号输入框并填写内容
6.查找发送验证码按钮并点击
7.查找并点击登录按钮

延时等待

在访问网站数据的时候加载需要一定的时间,没有加载完全的情况下代码
容易报错 此时需要等待页面数据加载完毕


# 解决措施
bro.implicitly_wait()

 完整代码

View Code

 

爬取京东商品数据

思路

1.访问京东首页并加入延时等待
2.查找搜索款并输入商品名称
3.按下enter键进入商品展示页
4.商品数据的展示页存在动态加载的情况 需要往下滚动 5.循环获取每一个li标签,筛选所需数据
6.图片数据存在懒加载现象
7.最后通过打印展示数据

单页爬取京东商品数据的完整代码

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

bro = webdriver.Chrome()
# 1.访问京东首页
bro.get('https://www.jd.com/')
bro.implicitly_wait(10)  # 延时等待
# 2.查找搜索款并输入商品名称
search_input = bro.find_element_by_id('key')
search_input.send_keys('显卡')
# 3.按下enter键进入商品展示页
search_input.send_keys(Keys.ENTER)

# 由于数据存在滚动加载的现象
for i in range(0, 8000, 1000):  # 千万不能直接到底 一定要有一个波段
    bro.execute_script('window.scrollTo(0,%s)' % i)
    time.sleep(0.5)

good_list = bro.find_elements_by_css_selector('li.gl-item')
# 循环获取每一个li标签 筛选所需数据
for li in good_list:
    # 图标标签的src属性
    img_tag = li.find_element_by_css_selector('div.p-img a img')
    img_src = img_tag.get_attribute('src')
    '''img标签的src属性存在懒加载现象 src没有就在data-lazy-img属性下'''
    if not img_src:
        img_src = 'https:' + img_tag.get_attribute('data-lazy-img')
    # 商品价格
    price_tag = li.find_element_by_css_selector('div.p-price strong')
    order_price = price_tag.text
    # 商品描述
    desc_tag = li.find_element_by_css_selector('div.p-name a em')
    order_desc = desc_tag.text
    # 商品链接
    link_tag = li.find_element_by_css_selector('div.p-name a')
    order_link = link_tag.get_attribute('href')
    # 商品销量
    commit_tag = li.find_element_by_css_selector('div.p-commit strong a')
    order_commit = commit_tag.text
    # 店铺名称
    shop_tag = li.find_element_by_css_selector('div.p-shop span a')
    shop_name = shop_tag.text
    # 店铺链接
    shop_link = shop_tag.get_attribute('href')
    # 通过打印展示数据 也可以数据持久化到表格文件
    print("""
    商品描述:%s
    商品价格:%s
    商品图片:%s
    商品链接:%s
    店铺名称:%s
    店铺链接:%s
    """ % (order_desc, order_price, img_src, order_link, shop_name, shop_link))

bro.close()
View Code

多页爬取

大致思路

由于我们使用的是selenuim所以此处只需要查找下一页按钮点击即可
将单页爬取数据的代码封装成一个函数 之后就可以循环爬取多页

 

知乎登录案例

 思路

一、研究发现电脑端知乎不登陆是无法直接访问首页的
二、在network监控中发送登录请求体数据为加密
三、搜索关键字encrypt通过断点调试查看到内部真实数据
四、此时可以研究e这个变量
五、python里调url解析库解个码
六、signature是加密的,得找出它的js加密算法
七、hamc的加密方式,sha-1的加密算法,用python的hmac,hashlib
八、在python里调用node.js去执行,执行js的库叫做 PyExecJS,需要下载
九、node.js中的运行环境和浏览器的运行环境是不一样的,浏览器中会有document,window对象
node.js的运行环境就一个单纯的jsv8引擎,所以需要依赖一个node.js的库jsdom来模拟浏览器环境
十、然后在js代码上面加上一段代码

 

posted @ 2021-10-06 13:35  陌若安然  阅读(50)  评论(0)    收藏  举报