爬虫入门到精通_实战篇11(使用代理处理反爬抓取微信文章)_PyQuery使用

news2024/11/18 6:18:33

1 目标

搜狗-微信这个网址来爬取微信的文章:
在这里插入图片描述
ps:登录后才能查看第10页之后的内容:
在这里插入图片描述
量翻页触发了网站的反爬虫措施,导致ip被封,需要进行解锁。
在这里插入图片描述
然而从doc中可以看到,请求失败的那页(状态码应该非200)被隐藏,只留下了状态码为200的这个验证页面。但是实际上,最后的那次请求返回状态码是302。

详情界面:
在这里插入图片描述

2 流程框架

  1. 抓取索引页内容:利用requests请求目标站点,得到索引网页HTML代码,返回结果。
  2. 代理设置:如果遇到302状态码,则证明IP被封,切换代理重试。
  3. 分析详情页内容:请求详情页,分析得到标题,正文等内容。
  4. 将数据保存到数据库:将结构化数据保存至MongDB。

3 实战

获取索引页

url:https://weixin.sogou.com/weixin?query=程序员&type=2&page=1
在这里插入图片描述
headers的部分,可以从网页审查中复制过来,并且构造为一个字典。

from urllib.parse import urlencode
import requests

base_url = 'https://weixin.sogou.com/weixin?'
headers={'Cookie': 'IPLOC=CN3205; SUID=E5C695243118960A000000005BD115E8; ld=Tlllllllll2b1SgolllllVsSVWklllllJJgpiyllll9lllllpylll5@@@@@@@@@@; SUV=1540429307839674; ABTEST=4|1541298543|v1; weixinIndexVisited=1; JSESSIONID=aaaKxagg6ZBOkf5LLDaBw; sct=2; ppinf=5|1541299811|1542509411|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZToyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8Y3J0OjEwOjE1NDEyOTk4MTF8cmVmbmljazoyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8dXNlcmlkOjQ0Om85dDJsdU9wakYzNVp1NklhNGhqYTdKUUxydTRAd2VpeGluLnNvaHUuY29tfA; pprdig=FzBX9Lki68sfImndi44lcV84vLEqbuPe8AXYRZYh5DtlawPVJEYr3bvv1oF8vmRfP0_rrTGYvtpqKwb39yNvJWqXl-Oh-29iaP0S893esgJdg2XNaxk7PNy5dcq1gMZOmf2kS_2YjNbV8WDULQnpjleCUcqcMMw3Av-FlSTgeh4; sgid=19-37785553-AVveXmPrwZ6BLoWTJ85UWicI; ppmdig=1541299811000000f0314597e0483df6fc4b14c41cacb024; PHPSESSID=0t7h64pmb3n0iphtp2j62i3a26; SUIR=A278AA1A3F3B46F2B8CFF48F3FD5AB76; SNUID=8ED5863612176BDC72510ED513A5E096',
'Host': 'weixin.sogou.com',
'Referer': 'https://weixin.sogou.com/weixin?query=%E7%A8%8B%E5%BA%8F%E5%91%98&type=2&page=39&ie=utf8',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
         }

def get_html(url):
    # 请求url
    try:
        response = requests.get(url,allow_redirects=False,headers =headers) #禁止302自动跳转处理
        if response.status_code == 200:
            return response.text
        if response.status_code == 302:
            pass
    except ConnectionError:
        return get_html(url) # 若失败,重试
# 获取索引页
def get_index(keyword,page):
    data = { # 将get请求所需要的参数构造为字典
        'query':keyword,
        'type':2,
        'page':page
    }
    url = base_url + urlencode(data) # 拼接url
    html = get_html(url)
    print(html)


if __name__ == '__main__':
    get_index('美景',1)

在这里插入图片描述
只请求了第一页,并不会触发反爬虫措施,改成循环会触发302,说明此时的ip已经被封:

def main():
    for page in range(1,101):
        html = get_index(keyword,page)
        print(html)

if __name__ == '__main__':
    main()

在这里插入图片描述

使用代理

出现ip被封的情况,需要更换代理进行请求。

from urllib.parse import urlencode
import requests

base_url = 'https://weixin.sogou.com/weixin?'
headers={'Cookie': 'IPLOC=CN3205; SUID=E5C695243118960A000000005BD115E8; ld=Tlllllllll2b1SgolllllVsSVWklllllJJgpiyllll9lllllpylll5@@@@@@@@@@; SUV=1540429307839674; ABTEST=4|1541298543|v1; weixinIndexVisited=1; JSESSIONID=aaaKxagg6ZBOkf5LLDaBw; sct=2; ppinf=5|1541299811|1542509411|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZToyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8Y3J0OjEwOjE1NDEyOTk4MTF8cmVmbmljazoyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8dXNlcmlkOjQ0Om85dDJsdU9wakYzNVp1NklhNGhqYTdKUUxydTRAd2VpeGluLnNvaHUuY29tfA; pprdig=FzBX9Lki68sfImndi44lcV84vLEqbuPe8AXYRZYh5DtlawPVJEYr3bvv1oF8vmRfP0_rrTGYvtpqKwb39yNvJWqXl-Oh-29iaP0S893esgJdg2XNaxk7PNy5dcq1gMZOmf2kS_2YjNbV8WDULQnpjleCUcqcMMw3Av-FlSTgeh4; sgid=19-37785553-AVveXmPrwZ6BLoWTJ85UWicI; ppmdig=1541299811000000f0314597e0483df6fc4b14c41cacb024; PHPSESSID=0t7h64pmb3n0iphtp2j62i3a26; SUIR=A278AA1A3F3B46F2B8CFF48F3FD5AB76; SNUID=8ED5863612176BDC72510ED513A5E096',
'Host': 'weixin.sogou.com',
'Referer': 'https://weixin.sogou.com/weixin?query=%E7%A8%8B%E5%BA%8F%E5%91%98&type=2&page=39&ie=utf8',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
         }
keyword = "美景"
proxy_pool_url = 'http://127.0.0.1:5000/get' #这是从web接口获取代理的地址

proxy = None #将代理设为全局变量
max_count = 5 #最大请求次数

#获取代理
def get_proxy():
    try:
        response = requests.get(proxy_pool_url)
        if response.status_code == 200:
            return response.text
        return None
    except ConnectionError:
        return None

#请求url
def get_html(url,count = 1):
    #打印一些调试信息
    print('Crawling:', url)
    print('Trying Count:', count)

    global proxy #引用全局变量
    if count >= max_count:#如果请求次数达到了上限
        print('Tried too many counts!')
        return None

    try :
        if proxy:# 如果现在正在使用代理
            proxies = {
                'http:':'http://'+ proxy #设置协议类型
            }
            response = requests.get(url, allow_redirects = False, headers = headers ,proxies = proxies)#使用有代理参数的请求
        else: #否则使用正常的请求
            response = requests.get(url, allow_redirects = False,headers=headers)#禁止自动处理跳转
        if response.status_code == 200:
            return response.text
        if response.status_code == 302:
            # 需要代理
            print("302!")
            proxy = get_proxy()
            if proxy:
                print('Using Proxy', proxy)
                return get_html(url)
            else:
                print('Get Proxy Failed')
                return None
    except ConnectionError as e:
        print('Error Occurred',e.args)#打印错误信息
        proxy = get_proxy() #若失败,更换代理
        count += 1 #请求次数+1
        return get_html(url,count) #重试
# 获取索引页
def get_index(keyword,page):
    data = { # 将get请求所需要的参数构造为字典
        'query':keyword,
        'type':2,
        'page':page
    }
    url = base_url + urlencode(data) # 拼接url
    html = get_html(url,5)
    print(html)


def main():
    for page in range(1,101):
        html = get_index(keyword,page)
        print(html)

if __name__ == '__main__':
    main()

在这里插入图片描述

分析详情页内容

解析索引页

在这里插入图片描述

def parse_index(html):
    doc = pq(html)
    items = doc('.news-box .news-list li .txt-box h3 a').items()
    for item in items:
        yield item.attr('href')

请求详情页

# 请求详情页
def get_detail(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except ConnectionError:
        return None

解析详情页

在这里插入图片描述

# 解析详情页
def parse_detail(html):
    doc = pq(html)
    title = doc('.rich_media_title').text()
    content = doc('.rich_media_content').text()
    date = doc('#post-date').text()
    nickname = doc('#js_profile_qrcode > div > strong').text()
    wechat = doc('#js_profile_qrcode > div > p:nth-child(3) > span').text()
    return {
        'title': title,
        'content': content,
        'date': date,
        'nickname': nickname,
        'wechat': wechat
    }

保存至MongoDB

client = pymongo.MongoClient('localhost')
db = client["weixin"]


def save_to_mongo(data):
    if db['articles'].update({'title': data['title']}, {'$set': data}, True):  # 如果不存在则插入,否则进行更新
        print('save to Mongo', data["title"])
    else:
        print('Save to Monge Failed', data['title'])

4 整体代码

from urllib.parse import urlencode
import requests
from pyquery import PyQuery as pq

base_url = 'https://weixin.sogou.com/weixin?'
headers={'Cookie': 'IPLOC=CN3205; SUID=E5C695243118960A000000005BD115E8; ld=Tlllllllll2b1SgolllllVsSVWklllllJJgpiyllll9lllllpylll5@@@@@@@@@@; SUV=1540429307839674; ABTEST=4|1541298543|v1; weixinIndexVisited=1; JSESSIONID=aaaKxagg6ZBOkf5LLDaBw; sct=2; ppinf=5|1541299811|1542509411|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZToyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8Y3J0OjEwOjE1NDEyOTk4MTF8cmVmbmljazoyNzolRTclOEMlQUElRTUlODYlQjIlRTUlODclODl8dXNlcmlkOjQ0Om85dDJsdU9wakYzNVp1NklhNGhqYTdKUUxydTRAd2VpeGluLnNvaHUuY29tfA; pprdig=FzBX9Lki68sfImndi44lcV84vLEqbuPe8AXYRZYh5DtlawPVJEYr3bvv1oF8vmRfP0_rrTGYvtpqKwb39yNvJWqXl-Oh-29iaP0S893esgJdg2XNaxk7PNy5dcq1gMZOmf2kS_2YjNbV8WDULQnpjleCUcqcMMw3Av-FlSTgeh4; sgid=19-37785553-AVveXmPrwZ6BLoWTJ85UWicI; ppmdig=1541299811000000f0314597e0483df6fc4b14c41cacb024; PHPSESSID=0t7h64pmb3n0iphtp2j62i3a26; SUIR=A278AA1A3F3B46F2B8CFF48F3FD5AB76; SNUID=8ED5863612176BDC72510ED513A5E096',
'Host': 'weixin.sogou.com',
'Referer': 'https://weixin.sogou.com/weixin?query=%E7%A8%8B%E5%BA%8F%E5%91%98&type=2&page=39&ie=utf8',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
         }
keyword = "美景"
proxy_pool_url = 'http://127.0.0.1:5000/get' #这是从web接口获取代理的地址

proxy = None #将代理设为全局变量
max_count = 5 #最大请求次数

client = pymongo.MongoClient('localhost')
db = client["weixin"]


def save_to_mongo(data):
    if db['articles'].update({'title': data['title']}, {'$set': data}, True):  # 如果不存在则插入,否则进行更新
        print('save to Mongo', data["title"])
    else:
        print('Save to Monge Failed', data['title'])

# 解析详情页
def parse_detail(html):
    doc = pq(html)
    title = doc('.rich_media_title').text()
    content = doc('.rich_media_content').text()
    date = doc('#post-date').text()
    nickname = doc('#js_profile_qrcode > div > strong').text()
    wechat = doc('#js_profile_qrcode > div > p:nth-child(3) > span').text()
    return {
        'title': title,
        'content': content,
        'date': date,
        'nickname': nickname,
        'wechat': wechat
    }

# 请求详情页
def get_detail(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except ConnectionError:
        return None


# 解析索引页
def parse_index(html):
    doc = pq(html)
    items = doc('.news-box .news-list li .txt-box h3 a').items()
    for item in items:
        yield item.attr('href')

#获取代理
def get_proxy():
    try:
        response = requests.get(proxy_pool_url)
        if response.status_code == 200:
            return response.text
        return None
    except ConnectionError:
        return None

#请求url
def get_html(url,count = 1):
    #打印一些调试信息
    print('Crawling:', url)
    print('Trying Count:', count)

    global proxy #引用全局变量
    if count >= max_count:#如果请求次数达到了上限
        print('Tried too many counts!')
        return None

    try :
        if proxy:# 如果现在正在使用代理
            proxies = {
                'http:':'http://'+ proxy #设置协议类型
            }
            response = requests.get(url, allow_redirects = False, headers = headers ,proxies = proxies)#使用有代理参数的请求
        else: #否则使用正常的请求
            response = requests.get(url, allow_redirects = False,headers=headers)#禁止自动处理跳转
        if response.status_code == 200:
            return response.text
        if response.status_code == 302:
            # 需要代理
            print("302!")
            proxy = get_proxy()
            if proxy:
                print('Using Proxy', proxy)
                return get_html(url)
            else:
                print('Get Proxy Failed')
                return None
    except ConnectionError as e:
        print('Error Occurred',e.args)#打印错误信息
        proxy = get_proxy() #若失败,更换代理
        count += 1 #请求次数+1
        return get_html(url,count) #重试
# 获取索引页
def get_index(keyword,page):
    data = { # 将get请求所需要的参数构造为字典
        'query':keyword,
        'type':2,
        'page':page
    }
    url = base_url + urlencode(data) # 拼接url
    html = get_html(url,5)
    print(html)


def main():
    for page in range(1, 101):
        html = get_index(keyword, page)
        if html:
            article_urls = parse_index(html)
            for article_url in article_urls:
                article_html = get_detail(article_url)
                if article_html:
                    article_data = parse_detail(article_html)
                    print(article_data)
                    if article_data:
                        save_to_mongo(article_data)

if __name__ == '__main__':
    main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1491248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vs2022 qt 关于lnk2001和2019同时报错的问题

需要像qt中添加模块,这里,缺少qtopenglwidgets模块

向上生长笔记

第一章 成为一个很厉害的人(持续输入,反复练习) 为什么要学习及如何学习 1、自毁趋势(熵增),故需要能量输入(负熵流) //引申:水往低处流是趋势,学习是逆趋势。 2、持续输入能量(物质和信息),…

C++ 根据公式计算椭圆任意点到中心的距离

#include <iostream> using namespace std;double fact(int x) //定义阶乘函数。注意是double类型 {double y x; //注意是double类型for (int i x-1; i > 0; i--)y * i;return y; };double My_sin(int x) //定义sin函数。注意是double类型 {double y 0; //注意是do…

SPI总线知识总结

1 SPI的时钟极性CPOL和时钟相位CPHA的设置 1.1 SPI数据传输位数 SPI传输数据过程中总是先发送或接收高字节数据&#xff0c;每个时钟周期接收器或发送器左移一位数据。对于小于16位的数据&#xff0c;在发送前必须左对齐&#xff0c;如果接收的数据小于16位&#xff0c;则采用软…

wordpress模板官网

移民wordpress主题 移民代办wordpress主题&#xff0c;适合做海外移民咨询的代理公司搭建wordpress企业官方网站使用。 https://www.jianzhanpress.com/?p5130 夏令营wordpress主题 绿色夏令营wordpress主题&#xff0c;适合做夏令营或户外拓展的公司搭建wordpress官方网站…

Go 与 Rust:导航编程语言景观

在当今构建软件时&#xff0c;开发者在编程语言上有着丰富的选择。两种脱颖而出的语言是 Go 和 Rust - 都很强大但却截然不同。本文将从各种因素比较这两种语言&#xff0c;以帮助您确定哪种更适合您的需求。 我们将权衡它们在并发、安全性、速度、互操作性等方面的方法。我们将…

【Redis】Redis入门

文章目录 一、Redis简介二、Redis的特性三、Redis的使用场景四、Redis可以做什么五、Redis不可以做什么六、CentOS7安装Redis5七、Redis通用命令 一、Redis简介 Redis 是⼀种基于 键值对&#xff08;key-value&#xff09; 的NoSQL数据库&#xff0c;与很多键值对数据库不同的…

Win UI3开发笔记(四)设置主题续2

本机深色主题下设置的背景颜色可以作用于整个对话框&#xff0c;本机浅色模式下设置的背景颜色只作用与下边的部分。 如果本机选深色&#xff0c;程序选浅色&#xff0c;设置为light只对上部分管用&#xff0c;下部分不管用。如图&#xff0c;左边那个hello按钮要看不见了。。…

Mac版2024 CleanMyMac X 4.14.6 核心功能详解

CleanMyMac 是 macOS 上久负盛名的系统清理工具&#xff0c;2018 年&#xff0c;里程碑式版本 CleanMyMac X 正式发布。不仅仅是命名上的变化&#xff0c;焕然一新的 UI、流畅的动画也让它显得更加精致。新增的系统优化、软件更新等功能&#xff0c;使得在日常使用 macOS 时有了…

力扣hot100:15.三数之和(双指针/哈希表)

分析&#xff1a; 三数和问题&#xff0c;这里和两数之和不一样&#xff0c;返回的是值&#xff0c;因此可以对其进行排序&#xff0c;使用双指针。 一、一层循环双指针 class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {sort…

react-beautiful-dnd组件报Unable to find draggable with id

一、问题现象 项目中使用react-beautiful-dnd组件实现可拖拽,但拖了1次后可能会出现拖拽异常(元素拖不动),打开控制台会发现有报错 二、解决方案 给Draggable组件和其下方的div添加了key就正常了,以下是我自己简单写的一个demo,可供参考 import {useState } from reac…

代码随想录算法训练营第32天—贪心算法06 | ● *738.单调递增的数字 ● *968.监控二叉树 ● 总结

*738.单调递增的数字 https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html 考点 贪心算法 我的思路 暴力解法 视频讲解关键点总结 几个关键点一&#xff0c;如果当前数位小于上一数位&#xff0c;如87&#xff0c;则应直…

redis06 redis事务

思维草图 redis事务认识 redis事务是一个单独的隔离操作&#xff0c;事务中的所有命令都会序列化、按顺序地执行&#xff0c;事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 redis事务的主要作用就是串联多个命令防止别的命令插队。 Multi、Exec、…

AWS 认证报名考试流程

AWS认证的考试包括&#xff0c;可以申请线上或者线下考试。 考试类型 线上&#xff1a; 优点&#xff1a;方便快捷无需通勤&#xff0c;随时约随时考&#xff0c;基本上每天都可以 缺点&#xff1a;对环境要求较高&#xff0c;屋子里只能有自己&#xff0c;而且不能有其他声音…

【Linux】Linux C编程

gcc编译器 gcc [options] [filenames] 其中&#xff0c;options是编译器所需要的选项参数&#xff0c;filenames是文件名。 gcc编译过程 C语言编译过程一般可以分为预处理、编译、汇编、链接四个步骤。 1.预处理阶段 预处理阶段主要处理宏定义和include&#xff0c;并进行语…

腾轩科技传媒讲解企业怎样做整合营销推广才有效果

当今信息爆炸的时代&#xff0c;企业如何才能从浩渺的市场中脱颖而出&#xff0c;触达目标消费者&#xff0c;实现品牌与销售的双增长&#xff1f;腾轩科技传媒讲解的整合营销推广正是解决这一问题的关键所在。它不仅仅是一种营销策略&#xff0c;更是一种全新的思维方式&#…

全面分析vcruntime140_1.dll无法继续执行代码的处理方法,3分钟修复vcruntime140_1.dll

如果系统弹出一个错误警告&#xff0c;指出“vcruntime140_1.dll无法继续执行代码”&#xff0c;这通常意味着您的Windows系统中缺失了一个关键的文件&#xff0c;或者该文件已损坏。​vcruntime140_1.dll​是随Visual C Redistributable for Visual Studio 2015, 2017和2019提…

购物车下单实现思路【vue】

文章目录 1、购物车1.1 使用pinia来存储购物车的状态1.2 用户将商品加入购物车的时候 2、点击结算按钮3、封装支付 1、购物车 在购物车页面会有一个点 提示当前购物车内商品的数量购物车内商品的展示购物车内商品的选中 1.1 使用pinia来存储购物车的状态 state: () > ({//…

web游戏-飞机大战

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的,私信本人,发演示地址,可以后再订阅,发源码,含60+小游戏源码。如五子棋、象棋、植物大战僵尸、开心消消乐、扑鱼达人、飞机大战等等 <!DOCTYPE html> <html lang=&q…

lowcode-engine快速开始

https://lowcode-engine.cn/site/docs/guide/quickStart/intro 安装node 需要node 14.17.0 pnpm安装多个node教程 pnpm env add --global 14.17.0下载demo deomo地址 安装依赖包 切换nodejs版本 pnpm env use --global 14.17.0 node -v切换到demo-general&#xff0c;安…