女生勿扰,只适合男孩子的python爬虫,里面东西不给钱统统白送

说真的,花了几天的时间来搞一个别人已经干过的项目,不知道是不是不值得,但是后面我自己上手做了之后,我才发现,这必须值得,崔大的书是2018年的,而现在网络的更新速度太快了,书本上的接口知识点都变了,废了老多时间才弄懂这些,不过我觉得也值,所以把代码加强了一下,实现了我的功能,下面做个简单的分享。

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤
QQ群:623406465

都2020年了还没爬过今日头条,你做爬虫是不是显得OUT了?但是没事,虽然现在的接口都变化了,那我就讲下2020年怎么搞今日头条妹子写真,这是一个改进的项目,里面参加了我自己的很多想法,比如有些很难懂的,我自己用简单的方式去实现了它,个人感觉还是实现的不错的,各位看官可以看看。

在这里插入图片描述

这个妹子觉得好看的评论区扣好看,直接教你怎么搞到手!


 

girls:

 

项目介绍:

利用简单的进程池Ajax数据爬取技术对今日头条关键词页面进行分析处理,然后获取每个页面的链接,从而获得所有图片的链接,然后打包下载
整个步骤我都会用小模块代码将其展示,实现不了的过来砍我! 就是这么的负责我跟你们说。


项目技术:

简单的进程池:

这里对进程的了解我也不是很多,简单的说下项目需要的函数:

from multiprocessing import Pool  # 调用函数库
p = Pool(4)  #  构造一个进程池,单位为4
p.close()  # 关闭进程
p.join()   # 开启进程

对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。

更多进程的知识点,还请各位大佬移步:廖老师的课堂


Ajax数据爬取:

网址的很多信息都不会直接全部出现在源代码里面,比如你刷网页,那些新刷出的网页就是一个个的通过ajax接口加载出来的,这是一种异步加载方式,原始的页面不会包含很多数据,数据都放在一个个接口里面,只有我们请求这个ajax接口,然后服务器后台收到这个接口信息,才会把数据返回,然后JavaScript分析这个数据,在渲染到浏览器页面上,这就是我们看到的模式,
现在越来越多的网页都是采用这个异步加载的方式,爬虫就现得没那么容易了,这个概念的讲的也拗口,我们直接开始实战吧!


项目作业:

最终作业效果图:

在这里插入图片描述
在这里插入图片描述


分析ajax接口获得数据:

数据包括:

  • 每个页面的标题
  • 每个页面的网址

目标网址: 今日头条关键词妹子

怎么知道他是不是ajax接口,主要有三点:

第一点

注意我这几个箭头,只要你在这里·查找·里面找不到与文章对应的文字还是链接什么的,那就可能是。
在这里插入图片描述

第二点

在这个XHR里面找到箭头的网址,点击,查看预览,这个时候你随意打开里面的东西,就能发现很多与文章相同的点
在这里插入图片描述

第三点

还是这张图,你可以看到X-requested里面的接口是XMLHttpRequets
如果三点同时满足,那他就是Ajax接口,然后异步加载出来的数据。

在这里插入图片描述

获得数据

在第二点的那张图我们可以看到有0,1,2,3,4,之类的,打开你会发现,都在这里面,图中我用箭头标红了,有标题和页面链接,只要获得这个页面链接,那么就很简单了。

在这里插入图片描述

编写程序:

获得json文件:

首先请求最开始的页面: https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3
但是我们不能这样直接把页面交给requests库直接干,因为这是一个ajax接口,如果不加入参数,很可能让你输入什么验证码还是拉动验证条什么,反正就是很麻烦,那我们就加入参数,具体措施如下:

def get_page(offset):    # offset偏移,因为每个ajax都是加载固定的页面数
                     # 这里是20,在第三点图上可以看得到
    global headers  # 全局变量  我后面还要用
    headers = {
        'cookie': 'tt_webid=6821518909792273933; WEATHER_CITY=%E5%8C%97%E4%BA%AC; SLARDAR_WEB_ID=b4a776dd-f454-43c6-81cd-bd37cb5fd0ec; tt_webid=6821518909792273933; csrftoken=4a2a6afcc9de4484af87a2ff8cba0638; ttcid=8732e6def0484fae975c136222a44f4932; s_v_web_id=verify_k9o5qf2w_T0dyn2r8_X6CE_4egN_9OwH_CCxYltDKYSQj; __tasessionId=oxyt6axwv1588341559186; tt_scid=VF6tWUudJvebIzhQ.fYRgRk.JHpeP88S02weA943O6b6-7o36CstImgKj1M3tT3mab1b',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Edg/81.0.416.68',
        'referer': 'https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3',
        'x-requested-with': 'XMLHttpRequest'
    }  # 头信息 加入参数
    params = {
        'aid': ' 24',
        'app_name': ' web_search',
        'offset': offset,
        'format': ' json',
        'keyword': ' 美女',
        'autoload': ' true',
        'count': ' 20',
        'en_qc': ' 1',
        'cur_tab': ' 1',
        'from': ' search_tab',
        'pd': ' synthesis',
        'timestamp': int(time.time())
    }
    url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params)  # 构造url, 使用到了urlencode() 函数 
    url = url.replace('=+', '=')  # 这里必须注意现在的网址根本不一样
    # print(url)          
    try:
        r = requests.get(url, headers=headers, params=params)
        r.content.decode('utf-8')
        if r.status_code == 200:
            return r.json()  # 返回json格式 因为全是字典类型
    except requests.ConnectionError as e:
        print(e)

这里必须注意一点,请求的网址已经改掉了,我在代码里面给了解释,仔细看看。

获得标题和网址:

def get_image(json):  # 获取图片
    if json.get('data'):  # 如果这个存在
        for item in json.get('data'):
            if item.get('title') is None:
                continue  # 如果标题是空值
            title = item.get('title')  # 获取标题
            if item.get('article_url') == None:
                continue
            url_page = item.get('article_url')
            # print(url_page)
            rr = requests.get(url_page, headers=headers)
            if rr.status_code == 200:
                pat = '<script>var BASE_DATA = .*?articleInfo:.*?content:(.*?)groupId.*?;</script>'  #  用正则大致匹配一下范围
                match = re.search(pat, rr.text, re.S)
                if match != None:
                    result = re.findall(r'img src&#x3D;\\&quot;(.*?)\\&quot;', match.group(), re.S)
                
                #  print(i.encode('utf-8').decode('unicode_escape')
                    # 转换编码方式 把\u之类的改掉
                    yield {
                        'title': title,
                        'image': result
                    }

这里获取的网页链接都是Unicode格式的,在后面的下载部分,我给了修改方案,这也是一个暗坑。

下载图片:

def save_image(content):
    path = 'D://今日头条美女//'  # 目录
    if not os.path.exists(path):  # 创建目录
        os.mkdir(path)
        os.chdir(path)
    else:
        os.chdir(path)
    # ------------------------------------------

    if not os.path.exists(content['title']):  # 创建单个文件夹
        if '\t' in content['title']:  # 以title为标题创建单个文件夹
            title = content['title'].replace('\t', '')  # 去除特殊符号 不然创建不了文件名称
            os.mkdir(title + '//')
            os.chdir(title + '//')
            print(title)
        else:
            title = content['title']
            os.mkdir(title + '//')  # 创建文件夹
            os.chdir(title + '//')
            print(title)
    else:  # 如果存在
        if '\t' in content['title']:  # 以title为标题创建单个文件夹
            title = content['title'].replace('\t', '')  # 去除特殊符号 不然创建不了文件名称
            os.chdir(title + '//')
            print(title)
        else:
            title = content['title']
            os.chdir(title + '//')
            print(title)
    for q, u in enumerate(content['image']):  # 遍历图片地址列表
        u = u.encode('utf-8').decode('unicode_escape')
        # 先编码在解码 获得需要的网址链接
        #  开始下载
        r = requests.get(u, headers=headers)
        if r.status_code == 200:
            # file_path = r'{0}/{1}.{2}'.format('美女', q, 'jpg')  # 文件的名字和地址,用三目运算符来调试文件夹的名字
            # hexdisgest() 返回十六进制图片
            with open(str(q) + '.jpg', 'wb') as fw:
                fw.write(r.content)
                print(f'该系列----->下载{q}张')

在U变量的时候进行了编码在解码操作,然后网址就正常很多了。

项目全部代码:

# -*- coding '':''  utf-8 -*-''
# @Time      '':''  2020/5/1  9:34''
# @author    '':''  沙漏在下雨''
# @Software  '':''  PyCharm''
# @优快云      '':''  https://me.youkuaiyun.com/qq_45906219''


import requests
from urllib.parse import urlencode  # 构造url
import time
import os
from hashlib import md5
from lxml import etree
from bs4 import BeautifulSoup
import re
from multiprocessing.pool import Pool


def get_page(offset):
    global headers
    headers = {
        'cookie': 'tt_webid=6821518909792273933; WEATHER_CITY=%E5%8C%97%E4%BA%AC; SLARDAR_WEB_ID=b4a776dd-f454-43c6-81cd-bd37cb5fd0ec; tt_webid=6821518909792273933; csrftoken=4a2a6afcc9de4484af87a2ff8cba0638; ttcid=8732e6def0484fae975c136222a44f4932; s_v_web_id=verify_k9o5qf2w_T0dyn2r8_X6CE_4egN_9OwH_CCxYltDKYSQj; __tasessionId=oxyt6axwv1588341559186; tt_scid=VF6tWUudJvebIzhQ.fYRgRk.JHpeP88S02weA943O6b6-7o36CstImgKj1M3tT3mab1b',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Edg/81.0.416.68',
        'referer': 'https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3',
        'x-requested-with': 'XMLHttpRequest'
    }  # 头信息 加入参数
    params = {
        'aid': ' 24',
        'app_name': ' web_search',
        'offset': offset,
        'format': ' json',
        'keyword': ' 美女',
        'autoload': ' true',
        'count': ' 20',
        'en_qc': ' 1',
        'cur_tab': ' 1',
        'from': ' search_tab',
        'pd': ' synthesis',
        'timestamp': int(time.time())
    }
    url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params)  # 构造url
    url = url.replace('=+', '=')  # 网址根本不一样
    # print(url)
    try:
        r = requests.get(url, headers=headers, params=params)
        r.content.decode('utf-8')
        if r.status_code == 200:
            return r.json()  # 返回json格式 因为全是字典类型
    except requests.ConnectionError as e:
        print(e)


def get_image(json):  # 获取图片
    if json.get('data'):  # 如果这个存在
        for item in json.get('data'):
            if item.get('title') is None:
                continue  # 如果标题是空值
            title = item.get('title')  # 获取标题
            # if item.get('image_list') is None:  # 进行判空
            #     continue
            # urls = item.get('image_list')  # 获得图片网址
            # for url in urls:  # 遍历这个urls
            #     url = url.get('url')
            #     # 使用正则拼接网址
            #     url = 'http://p1.pstatp.com/origin/' + 'pgc-image/' + url.split('/')[-1]
            if item.get('article_url') == None:
                continue
            url_page = item.get('article_url')
            # print(url_page)
            rr = requests.get(url_page, headers=headers)

            if rr.status_code == 200:
                pat = '<script>var BASE_DATA = .*?articleInfo:.*?content:(.*?)groupId.*?;</script>'
                match = re.search(pat, rr.text, re.S)
                if match != None:
                    result = re.findall(r'img src&#x3D;\\&quot;(.*?)\\&quot;', match.group(), re.S)
                    # for i in result:
                    #     print(i.encode('utf-8').decode('unicode_escape')
                    # 转换编码方式 把\u之类的改掉
                    yield {
                        'title': title,
                        'image': result
                    }
            #  格式出错,这里产生了十六进制的数值, 网址获取不了,明天看
            # yield {
            #     'title': title,
            #     'image': url
            # }  # 返回标题和网址


def save_image(content):
    path = 'D://今日头条美女//'  # 目录
    if not os.path.exists(path):  # 创建目录
        os.mkdir(path)
        os.chdir(path)
    else:
        os.chdir(path)
    # ------------------------------------------

    if not os.path.exists(content['title']):  # 创建单个文件夹
        if '\t' in content['title']:  # 以title为标题创建单个文件夹
            title = content['title'].replace('\t', '')  # 去除特殊符号 不然创建不了文件名称
            os.mkdir(title + '//')
            os.chdir(title + '//')
            print(title)
        else:
            title = content['title']
            os.mkdir(title + '//')  # 创建文件夹
            os.chdir(title + '//')
            print(title)
    else:  # 如果存在
        if '\t' in content['title']:  # 以title为标题创建单个文件夹
            title = content['title'].replace('\t', '')  # 去除特殊符号 不然创建不了文件名称
            os.chdir(title + '//')
            print(title)
        else:
            title = content['title']
            os.chdir(title + '//')
            print(title)
    for q, u in enumerate(content['image']):  # 遍历图片地址列表
        u = u.encode('utf-8').decode('unicode_escape')

        # 先编码在解码 获得需要的网址链接
        #  开始下载
        r = requests.get(u, headers=headers)
        if r.status_code == 200:
            # file_path = r'{0}/{1}.{2}'.format('美女', q, 'jpg')  # 文件的名字和地址,用三目运算符来调试文件夹的名字
            # hexdisgest() 返回十六进制图片
            with open(str(q) + '.jpg', 'wb') as fw:
                fw.write(r.content)
                print(f'该系列----->下载{q}张')


def main(offset):
    json = get_page(offset)
    get_image(json)
    for content in get_image(json):
        try:
            # print(content)
            save_image(content)
        except FileExistsError and OSError:
            print('创建文件格式错误,包含特殊字符串:')
            continue


if __name__ == '__main__':
    pool = Pool()
    groups = [j * 20 for j in range(8)]
    pool.map(main, groups) # 传offset偏移量
    pool.close()
    pool.join()

项目体会:

这是我第一个爬虫项目,之前都是很简单的,这一次有点麻烦,总之,对于困难我们还是别怕,不会就百度,一直百度一定出结果!

项目修复:

  • 正确的拼接网址,修复了data = None 的bug,在获得json文件里面得到了体现
  • 加入必要的参数,避免了验证码和验证条的出现,这也很棒 =。=
  • 进行编码解码操作, 修改了\u格式下的链接不匹配问题,在获得网址的时候我也提到了
  • 下载图片的时候使用了子文件夹的处理,让下载的图片不会那么杂乱
  • 下载采用了简单的线程池问题,加快了下载的速度
<think>好的,我现在需要帮助用户解决使用Python和uiautomator2通过while循环滑动查找并点击'勿扰模式'的问题。首先,我得回忆一下uiautomator2的基本操作,尤其是元素查找和滑动的方法。 用户提到要用while循环结合滑动来查找元素,这可能是因为目标元素在当前屏幕,需要断滑动直到找到为止。首先,我需要确定如何检测元素是否存在。uiautomator2的exists()方法可以判断元素是否在当前的界面中。如果存在,就点击;如果存在,就滑动屏幕,继续循环。 接下来要考虑滑动的操作。通常,模拟器的屏幕滑动可以使用swipe方法,需要指定起始和结束的坐标。比如,从屏幕底部滑到顶部,这样可以实现向上翻页的效果。坐标可能需要根据模拟器的分辨率调整,但雷电模拟器一般默认是1080x1920,所以起始点可能是(500, 1600),终点是(500, 400),这样滑动的距离足够。 然后,循环的条件。这里需要避免无限循环,比如设置最大尝试次数,比如10次,防止找到元素时程序一直运行。所以,在while循环中加入一个计数器,每次滑动后计数器加一,超过次数就跳出循环并提示未找到。 还需要处理可能的异常情况,比如滑动过程中是否有其他弹窗干扰,或者元素的属性是否正确。用户提供的元素文本是'Do Not Disturb Mode',但实际应用中可能有同的描述,比如中文环境下的“勿扰模式”,但用户可能已经处理了这一点,所以按用户给出的文本处理。 代码结构大致是:初始化设备连接,然后进入循环,检查元素是否存在,存在则点击并退出循环,否则滑动,直到达到最大次数。需要注意的是,每次滑动后可能需要等待一段时间,让界面稳定,比如使用time.sleep(1)。 此外,元素的选择器应该使用text或description属性,但有时候文本可能包含换行或者空格,可能需要使用正则表达式或模糊匹配,比如contains或matches方法。但用户给出的例子是直接使用text等于'Do Not Disturb Mode',所以暂时按精确匹配处理。 最后,测试代码是否能在雷电模拟器中正常运行,确保uiautomator2的服务已经正确安装(通过运行d.init()会自动安装)。如果用户遇到元素无法找到的情况,可能需要检查元素的属性是否正确,或者是否在正确的页面中。</think>以下是如何使用Python的uiautomator2库实现滑动查找并点击'勿扰模式'的解决方案: ```python from uiautomator2 import Device import time # 连接雷电模拟器(确保adb已连接) d = Device() max_retries = 10 # 最大尝试次数 found = False while max_retries > 0: # 检查目标元素是否存在 if d(text='Do Not Disturb Mode').exists: d(text='Do Not Disturb Mode').click() found = True break # 执行滑动操作(从下往上滑动屏幕) d.swipe(500, 1600, 500, 400, 0.5) # 坐标需根据模拟器分辨率调整 max_retries -= 1 time.sleep(1) # 等待界面稳定 if not found: print("未找到目标元素") else: print("已成功操作") ``` ### 关键点说明 1. **元素定位**:使用`d(text='...')`选择器定位控件,若需模糊匹配可用`d(textContains='勿扰')` 2. **滑动参数**: - `swipe(start_x, start_y, end_x, end_y, duration)` - 坐标值需根据模拟器分辨率调整(雷电模拟器默认1080x1920) 3. **循环控制**: - 设置最大重试次数防止死循环 - 每次滑动后添加`time.sleep()`保证界面稳定[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值