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

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 requestsbase_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):# 请求urltry:response = requests.get(url,allow_redirects=False,headers =headers) #禁止302自动跳转处理if response.status_code == 200:return response.textif response.status_code == 302:passexcept ConnectionError:return get_html(url) # 若失败,重试
# 获取索引页
def get_index(keyword,page):data = { # 将get请求所需要的参数构造为字典'query':keyword,'type':2,'page':page}url = base_url + urlencode(data) # 拼接urlhtml = 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 requestsbase_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.textreturn Noneexcept 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 Nonetry :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.textif 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 Noneexcept ConnectionError as e:print('Error Occurred',e.args)#打印错误信息proxy = get_proxy() #若失败,更换代理count += 1 #请求次数+1return get_html(url,count) #重试
# 获取索引页
def get_index(keyword,page):data = { # 将get请求所需要的参数构造为字典'query':keyword,'type':2,'page':page}url = base_url + urlencode(data) # 拼接urlhtml = 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.textreturn Noneexcept 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 pqbase_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.textreturn Noneexcept 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.textreturn Noneexcept 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 Nonetry :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.textif 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 Noneexcept ConnectionError as e:print('Error Occurred',e.args)#打印错误信息proxy = get_proxy() #若失败,更换代理count += 1 #请求次数+1return get_html(url,count) #重试
# 获取索引页
def get_index(keyword,page):data = { # 将get请求所需要的参数构造为字典'query':keyword,'type':2,'page':page}url = base_url + urlencode(data) # 拼接urlhtml = 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.rhkb.cn/news/269546.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【力扣白嫖日记】1045.买下所有产品的客户

前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。 今日题目: 1045.买下所有产品的客户 表:Customer 列名类型customer_idintproduct_keyint 该表可能包含重复…

【Vue3】深入理解Vue中的ref属性

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

MyCAT集群——MyCAT2如何配置读写分离

先搭载MySQL一主两从 192.168.20.110MyCAT192.168.20.111Master192.168.20.112slave1192.168.20.113slave2 配置就不写了,比较基础,写一下步骤 1.进入mysql配置文件或者其子配置文件,添加server_id,开启gtidgtid_modeON,enforce-gtid-cons…

个人社区 项目测试

目 录 一.背景及介绍二.功能详情三.手动测试1.编写测试用例2.测试 一.背景及介绍 该项目采用了前后端分离技术,把我们的数据保存到数据库中,操作对象是用户和个人文章编辑保存,前端的页面实现了登录,列表,编辑&#x…

学习JAVA的第十三天(基础)

目录 API之Arrays 将数组变成字符串 二分查找法查找元素 拷贝数组 填充数组 排序数组 Lambda表达式 集合的进阶 单列集合 体系结构 Collection API之Arrays 操作数组的工具类 将数组变成字符串 //将数组变成字符串char[] arr {a,b,c,d,e};System.out.println(Arra…

leetcode--接雨水(双指针法,动态规划,单调栈)

目录 方法一:双指针法 方法二:动态规划 方法三:单调栈 42. 接雨水 - 力扣(LeetCode) 黑色的是柱子,蓝色的是雨水,我们先来观察一下雨水的分布情况: 雨水落在凹槽之间,在一个凹槽的…

第十三届蓝桥杯嵌入式省赛程序设计详细题解

第十三届蓝桥杯嵌入式省赛题目相对于第十二届较为简单,没有那么多串口的数据处理以及判断! 第十三届省赛主要是制作一个可由串口设置密码的密码锁。本实验中,我们将用到LED模块、按键模块、串口模块、定时器的PWM模块以及官方会提供源码的LC…

01、MongoDB -- 下载、安装、配置文件等配置 及 副本集配置

目录 MongoDB -- 下载、安装、配置 及 副本集配置启动命令启动 mongodb 的服务器(单机和副本集)启动单机模式的 mongodb 服务器启动副本集的 3 个副本节点(mongodb 服务器) 启动 mongodb 的客户端 MongoDB 下载MongoDB 安装1、解压…

UE5 UE4 不同关卡使用Sequence动画

参考自:关于Datasmith导入流程 | 虚幻引擎文档 (unrealengine.com) 关卡中的Sequence动画序列,包含特定关卡中的Actor的引用。 将同一个Sequcen动画资源放入其他关卡,Sequence无法在新关卡中找到相同的Actor,导致报错。 Sequen…

android Service 与 activity 通信 并不断传数据

注:这只是个Demo 以下载为案例,实现开启下载,暂停下载,下载进度不断发送给activity class DownloadService : Service() {override fun onBind(intent: Intent?): IBinder? {return MyBinder()}inner class MyBinder : Binder…

Java知识点总结(二)

ID生成策略 主键自增id 主键自动增长,不用手工设值、数字型,占用空间小、检索非常有利、有顺序,不会重复,但在迁移旧数据是会出现id冲突 UUID 基于时间,计数器和地址生成32位的id redis生成id 原子性自增,并…

Flask入门一(介绍、Flask安装、Flask运行方式及使用、虚拟环境、调试模式、配置文件、路由系统)

文章目录 一、Flask介绍二、Flask创建和运行1.安装2.快速使用3.Flask小知识4.flask的运行方式 三、Werkzeug介绍四、Jinja2介绍五、Click CLI 介绍六、Flask安装介绍watchdog使用python--dotenv使用(操作环境变量) 七、虚拟环境介绍Mac/linux创建虚拟环境…

Android Gradle开发与应用 (三) : Groovy语法概念与闭包

1. Groovy介绍 Groovy是一种基于Java平台的动态编程语言,与Java是完全兼容,除此之外有很多的语法糖来方便我们开发。Groovy代码能够直接运行在Java虚拟机(JVM)上,也可以被编译成Java字节码文件。 以下是Groovy的一些…

2024.02.29作业

1. TCP模型 server #include "test.h"#define SER_IP "192.168.191.128" #define SER_PORT 9999int main(int argc, char const *argv[]) {int sfd -1;sfd socket(AF_INET, SOCK_STREAM, 0);if (-1 sfd){perror("socket error");return -1;…

Java生成 word报告

Java生成 word报告 一、方案比较二、Apache POI 生成三、FreeMarker 生成 在网上找了好多天将数据库信息导出到 word 中的解决方案,现在将这几天的总结分享一下。总的来说,Java 导出 word 大致有 5 种。 一、方案比较 1. Jacob Jacob 是 Java-COM Bri…

ECMAScript6

课程链接 目录 相关介绍什么是ECMA什么是ECMAScript为什么学习ES6 letconst变量解构赋值模板字符串对象简化写法箭头函数函数参数的默认值rest参数扩展运算符Symbol迭代器生成器函数与调用Promise介绍与基本用法Promise封装读取文件Promise.prototype...then方法Promise.catch…

光影交织:汽车穿越隧道的视觉盛宴

在繁忙的城市中,隧道成为了连接两端的重要通道。而对于汽车来说,穿越隧道不仅是一次简单的空间转移,更是一场融合了视觉、技术与安全的独特体验。 当汽车缓缓驶入隧道,外界的光线逐渐减弱,隧道内部的光线开始发挥作用。…

向量数据库Chroma教程

引言 随着大模型的崛起,数据的海洋愈发浩渺无垠。受限于token的数量,无数的开发者们如同勇敢的航海家,开始在茫茫数据之海中探寻新的路径。他们选择了将浩如烟海的知识、新闻、文献、语料等,通过嵌入算法(embedding)的神秘力量,转化为向量数据,存储在神秘的Chroma向量…

JavaScript基础知识(三)

JavaScript基础知识(三) 一、事件1. 事件绑定2.事件流2.1 事件捕获与事件冒泡 3.事件对象扩展3.1 阻止事件冒泡3.2 事件默认行为 4.事件委托5.事件类型5.1 鼠标事件5.2 键盘事件5.3 触屏事件 二、计时器方法1. setInterval 与 clearInterval2. setTimeou…

【Unity】使用ScriptableObject存储数据

1.为什么要用ScriptableObject? 在游戏开发中,有大量的配置数据需要存储,这个时候就需要ScriptableObject来存储数据了。 很多人会说我可以用json、xml、txt,excel等等 但是你们有没有想过,假设你使用的是json&#x…