python wechatsougou_使用Python的requests库模拟登陆微信搜狗,爬取100X10篇微信文章并保存到MySQL...

2023-11-11

自学的python和爬虫技术。使用到Redis,MySQL数据库;request请求模块;re,Xpath解析模块;dumps, loads序列化和反序列化。还可以配合代理池使用。

爬取的是https://weixin.sogou.com/。网站只能微信扫码登陆,不登录只能访问十页,这里

使用Session保持会话实现登陆状态爬取100页,cookie是自己添加的。

第一次发文,试一试页面效果hhhh,有机会再具体解析思路。

算是我自学的一个阶段性成果,因为我是外行,代码中肯定有些愚蠢的地方,贴出源代码来供大家批判指正。

python3.6环境,运行确保安装相关python库以及数据库

from requests import Request, ConnectionError, ReadTimeout

from requests import Session

from pickle import dumps, loads

from urllib.parse import urlencode

from lxml import etree

import pymysql

#控制代理池的开启

from run import main

import time

import re

from redis import StrictRedis

TIMEOUT = 10

MAX_FAILED_TIME = 3

REDIS_KEY = 'weixinrequests_liu'

REDIS_HOST = "localhost"

REDIS_PORT = 6379

REDIS_PASSWORD = None

MYSQL_HOST = "localhost"

MYSQL_NAME = 'root'

MYSQL_PASSWORD = '*****'

MYSQL_DATABASE = 'samp_db'

MYSQL_PORT = 3306

PROXY_POOL_URL = 'http://api.xdaili.cn/xdaili-api//greatRecharge/getGreatIp?spiderId=2f80314147e34f04bf5705006d837a86&orderno=YZ2018112477906eltR9&returnType=1&count=10'

# PROXY_POOL_URL = 'http://localhost:5555/random'

KEY_WORDS = "杨超越"

COOKIE = 'SUV=0081272D655E8569592959DA71D95636; SUID=8AB1E7652F20910A00000000595B0BDA; ld=4Zllllllll2bLZA5lllllVsKxm1lllllBqf3vZllll9lllllxllll5@@@@@@@@@@; ABTEST=3|1543134403|v1; IPLOC=CN3100; weixinIndexVisited=1; sct=1; ppinf=5|1543150392|1544359992|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZToxODolRTYlOUQlOEUlRTUlOEQlOUF8Y3J0OjEwOjE1NDMxNTAzOTJ8cmVmbmljazoxODolRTYlOUQlOEUlRTUlOEQlOUF8dXNlcmlkOjQ0Om85dDJsdUgyb3R2dks1bFoydFpTU1Q3MDJWY0VAd2VpeGluLnNvaHUuY29tfA; pprdig=QPtri4HHDEm4Gz9hxTvUj8MO9ymKgOe2EgkwA3uuYG0JIjd1IM8NnWkE6f1vrIt4mlMoC1Nmomb6ntUbGAjANhGeEkJOid0_Yk4g0yBHTA0FQ3_WMsbYhS0SQN_Sbmvj66AVXN93ZhbqAzmflqUoyNdw7YGswhD3tZ7J0xu0i0U; sgid=12-38075013-AVv6mzhP6ltMX5qfqx8JPJc; SUIR=AC6DB982E7ED939ECB44C2A1E85C066B; SNUID=AA6ABE84E0E49B9DDE6C0D11E196941C; JSESSIONID=aaaZoBR-hzstpadzRe7Cw; ppmdig=1543197423000000309d9113ade27bf0e5a2598fd5f1caba'

START_ID = 10

DIC_TIME = 0

HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Accept-Encoding': 'gzip, deflate, br',

'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',

'Cache-Control': 'max-age=0',

'Connection': 'keep-alive',

'Cookie': COOKIE,

# 'Host':'weixin.sogou.com',

'Upgrade-Insure-Request': '1',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',

}

TABLE_NAME = 'seshi3'

MAX_PAGE = 100

PROXY_ON = False

class MySQL():

def __init__(self, host=MYSQL_HOST, username=MYSQL_NAME, password=MYSQL_PASSWORD, port=MYSQL_PORT, database=MYSQL_DATABASE):

try:

self.db = pymysql.connect(host=host, user=username, password=password, db=database, port=port)

self.cursor = self.db.cursor()

except Exception as e:

print(e)

def insert(self, table, data):

keys = ','.join(data.keys())

values = ','.join(len(data)*['%s'])

print(values)

sql_query = 'INSERT INTO {}({}) values ({})'.format(table, keys, values)

try:

self.cursor.execute(sql_query, tuple(data.values()))

self.db.commit()

print('真的插入成功了')

except Exception as e:

print(e,'插入失败')

self.db.rollback()

class WeixinRequest(Request):

def __init__(self, url, callback, method='GET', headers=None, need_proxy=False, fail_time=0, timeout=TIMEOUT):

Request.__init__(self, method, url, headers)

self.callback = callback

self.need_proxy = need_proxy

self.fail_time = fail_time

self.timeout = timeout

class RedisQueue():

def __init__(self):

self.db = StrictRedis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD)

def add(self, request):

if isinstance(request, WeixinRequest):

return self.db.rpush(REDIS_KEY, dumps(request))

else:

print("meiyoujiaaa")

return False

def pop(self):

if self.db.llen(REDIS_KEY):

return loads(self.db.lpop(REDIS_KEY))

else:

return False

def empty(self):

return self.db.llen(REDIS_KEY) == 0

def get_proxy():

if PROXY_ON:

try:

response = requests.get(PROXY_POOL_URL)

if response.status_code == 200:

print('获得代理', response.text)

return response.text

return None

except Exception as e:

print(e)

return None

False

class Spider():

base_url = r'https://weixin.sogou.com/weixin'

session = Session()

queue = RedisQueue()

mysql = MySQL()

def __init__(self, dictime, start_id, table_name, headers, key_words, max_page):

self.rtime = start_id

self.dictime = dictime

self.start_id = start_id

self.table_name = table_name

self.headers = headers

self.key_words = key_words

self.max_page = max_page

def start(self):

self.session.headers.update(self.headers)

start_url = 'https://weixin.sogou.com/weixin?query={}&_sug_type_=&sut=4722&lkt=1%2C1542979381375%2C1542979381375&s_from=input&_sug_=y&type=2&sst0=1542979381478&page={}&ie=utf8&w=01019900&dr=1'.format(self.key_words, self.start_id)

wexin_request = WeixinRequest(start_url, callback=self.parse_index, need_proxy=False)

self.queue.add(wexin_request)

print(wexin_request.url, "是开始获取的url")

def parse_index(self, r):

html = etree.HTML(r.text)

html_li = html.xpath("//ul[@class='news-list']/li")

for url_list in html_li:

url = url_list.xpath(".//h3/a/@href")[0]

print('parese_index获取到这个微信url(dictime,rtime)', (self.dictime,self.rtime), url)

self.dictime += 1

yield WeixinRequest(url=url, callback=self.parse_detail, need_proxy=True, headers=self.headers, method='GET')

pattern2 = re.compile(r'''sogou_next.*?="(.*?)"''')

next = re.findall(pattern2, r.text)[0] if len(re.findall(pattern2, r.text)) >= 1 else 0

if next:

next_url = self.base_url + next

self.rtime += 1

print('哈哈哈parese_index自动获取到这个下一页url(dictime,rtime)', (self.dictime, self.rtime), next_url)

yield WeixinRequest(url=next_url, callback=self.parse_index, need_proxy=True, headers=self.headers)

else:

next_url = 'https://weixin.sogou.com/weixin?query={}&_sug_type_=&sut=4722&lkt=1%2C1542979381375%2C1542979381375&s_from=input&_sug_=y&type=2&sst0=1542979381478&page={}&ie=utf8&w=01019900&dr=1'.format(self.key_words,self.rtime+1)

self.rtime += 1

if self.rtime <= self.max_page:

print('啊啊啊自动构造这个下一页url(dictime,rtime)', (self.dictime, self.rtime), next_url)

yield WeixinRequest(url=next_url, callback=self.parse_index, need_proxy=True, headers=self.headers)

def parse_detail(self, response):

r = response.text

pattern = re.compile(r'publish_time = "(.*?)"')

date = re.findall(pattern, r)[0] if len(re.findall(pattern, r))>=1 else "日期出错"

# print(r.text)

html = etree.HTML(r)

title = html.xpath("//h2[@class='rich_media_title']//text()")[0].strip() if len(html.xpath("//h2[@class='rich_media_title']//text()"))>=1 else "标题出错"

lend = len(html.xpath("//div[contains(@id,'meta_content') and @class='rich_media_meta_list']/span"))

wechat = html.xpath("//div[contains(@id,'meta_content') and @class='rich_media_meta_list']/span[last()]/a/text()")[0].strip('\n').strip() if len(html.xpath("//div[contains(@id,'meta_content') and @class='rich_media_meta_list']/span[last()]/a/text()"))>=1 else "wechat出错"

pattern3 = re.compile(r'''js_name.*?>(.*?)

nickname = re.findall(pattern3,r)[0].strip('\n').strip() if len(re.findall(pattern3,r))>0 else 'nickname出错'

if lend == 3:

original = \

html.xpath("//div[contains(@id,'meta_content') and @class='rich_media_meta_list']/span[last()-2]/text()")[0].strip('\n').strip() if len(html.xpath("//div[contains(@id,'meta_content') and @class='rich_media_meta_list']/span[last()-2]/text()"))>=1 else "original出错"

else:

original = ''

content_list = html.xpath("//div[@id='img-content']/div[2]//p//text()") if len(html.xpath("//div[@id='img-content']/div[2]//p//text()")) >=1 else "内容出错"

neirong = ""

for i in content_list:

neirong += i.strip()

data = {

'title':title,

'original':original,

'nickname':nickname,

'date': date,

'wechat':wechat,

'content':neirong

}

yield data

def schedule(self):

while not self.queue.empty():

print("开始调度次", "\n", "="*20)

weixin_request = self.queue.pop()

print("调度选出了这个url", weixin_request.url, '选出了这个url')

# 存在两种可能的请求

callback = weixin_request.callback

# 先请求

response = self.request(weixin_request)

print(response, '获得相应*********')

if hasattr(response, 'status_code'):

print(response.status_code, '上面url的状态')

if response and (response.status_code == 200):

# 再解析

results = list(callback(response))

if results:

# print("解析结果",results)

for result in results:

if isinstance(result, WeixinRequest):

self.queue.add(result)

print('解析结果,搜索页文章列表', result.url)

# self.rtime += 1

if isinstance(result, dict):

self.mysql.insert(table=self.table_name, data=result)

print("插入到MYSQL",result)

else:

self.error(weixin_request)

else:

self.error(weixin_request)

else:

self.error(weixin_request)

def error(self, weixin_request):

# 接受一个请求

print("休息二秒")

weixin_request.fail_time += 1

print("请求失败", weixin_request.fail_time, "次", weixin_request.url)

time.sleep(20)

if weixin_request.fail_time < MAX_FAILED_TIME:

self.queue.add(weixin_request)

def request(self,weixin_request):

try:

proxy = get_proxy()

print("代理状态,", proxy)

if proxy:

proxies ={

'http': 'http://' + proxy,

'https': 'https://' + proxy

}

return self.session.send(weixin_request.prepare(), proxies=proxies)

time.sleep(3)

return self.session.send(weixin_request.prepare())

except (ConnectionError, ReadTimeout) as e:

print(e)

return False

def run(self):

self.start()

self.schedule()

if __name__ == '__main__':

#mysql内容编码utf8m4

spider = Spider(

dictime=DIC_TIME,

start_id=START_ID,

table_name=TABLE_NAME,

key_words=KEY_WORDS,

headers=HEADERS,

max_page=MAX_PAGE

)

spider.run()

print(spider.rtime, "请求页数")

print(spider.dictime, "请求篇数")

# MySQL存储结果

# 运行结果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python wechatsougou_使用Python的requests库模拟登陆微信搜狗,爬取100X10篇微信文章并保存到MySQL... 的相关文章

  • 前端组件Bootstrap4(学习笔记一)

    Hello 大家好 今天要分享的文章仍然是关于前端的 为什么迟迟没有关于Android相关的文章呢 其实这个公众号一开始 我就有明确的表示 它不仅仅局限于Android 我希望它可以博采众长 以Android为主 其它技术为辅 夹杂一些社会
  • Unity3D之UI按键绑定事件案例(七)

    七 多个按键事件存在的时候怎么区分 怎么同时绑定事件 下面的案例可以给出答案 第一步 通过Hierarchy面板创建多个button 第二步 创建一个名为Buttons的脚本 代码如下 public class MyEventArgs pu
  • web前端可视化开发,前端优秀实践指南,知乎上已获万赞

    前言 跳槽 这在 IT 互联网圈是非常普遍的 也是让自己升职加薪 走上人生巅峰的重要方式 那么作为一个普通的Android程序猿 我们如何才能斩获大厂offer 呢 疫情向好 面试在即 还在迷茫踌躇中的后浪们 如何才能在面试中让自己脱颖而出
  • Qt自定义控件 —— 颜色选择组合控件

    在开始阅读本文之前 如果您有学习创建Qt自定义控件并在其他项目中引用的需求 请参考 Linux系统下在Qt Creator中创建自定义控件并在其他项目中引用https blog csdn net YMGogre article detail
  • head 请求了解过吗?如何用 get 模拟 head 请求?不需要服务器返回数据,怎么实现?

    HEAD请求是HTTP 1 1协议中定义的一个请求方法 与GET请求相似 但只请求目标URL的头部 不请求实际的数据或者说正文内容 其主要用途是 检查资源是否被修改 检查资源是否存在 校验缓存有效性 了解服务器性能 要用GET请求模拟HEA
  • [已解决]“ImportError: No module named flask”

    1 删除原有的用大写开头的Flask插件 pip uninstall Flask 2 yum安装 flask yum install python flask 3 等待安装完成就可以允许程序啦 100 有用
  • 快速编写json数据

    1 打开idea 2 新建txt文件 alt 单击快速加 编写json数据
  • C语言面试必问的经典问题(纯”gan“货)

    C语言面试必问的经典问题 1 预处理 1 预编译 编译过程最先做的工作是啥 何时需要预编译 指令有什么 答 预编译就是预处理 就是把一些文本的替换工作工作 预编译指令 include ifdef ifndef else endif 编译 字
  • 高德地图Js API的使用

    申请JSAPI的开发者key 申请地址 http lbs amap com dev key 引入高德地图JavaScript API文件 创建地图容器 在页面body里你想展示地图的地方创建一个div 容器 并指定id标识 div div
  • Python-Pyqt6之QIntValidator,QDoubleValidator无法限制数值范围的正则表达式解决方案

    在使用Pyqt6进行GUI设计的时候 在需要输入数值 整型 浮点型 的时候选择使用了QLineEdit这个组件控件 详情介绍 QLineEdit组件详情 QLineEdit自带的setValidator包含 QIntValidator QD
  • promise函数几种写法与坑

    promise是ES6中引入的处理异步函数的强大特性 但是对promise的不恰当使用可能会达不到最终目的 对这个问题的探究来源于这篇文章关于promises 你理解了多少 几个异步函数如下 resolve或reject在回调函数里被调用
  • 网络编程的几种I/O模式

    1 非阻塞I O 非阻塞I O 若想网络编程时调用I O函数不想让程序阻塞 需要使用I O复用技术 一个方法是poll 轮询 所谓轮询就是执行函数时 如果内核不能立即对应用的函数进行响应时 就返回给应用一个错误 而应用不停的循环调用该函数
  • JavaScript表示不背小数计算存在误差的锅

    浮点数的最高精度是17位小数 但是在实际计算时会产生莫名其妙的问题 如0 1 0 2的结果不是0 3 而是0 30000000000000004 这个舍入误差会导致无法测试特定的浮点数值 例如 var a 0 1 b 0 2 if a b
  • 【数据结构】采用邻接矩阵表示法创建无向网、无向图、有向图、有向网

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 一 无向网 权值 对称 1 思路 2 代码 3 运行结果 三 其他 1 无向图 0 1 对称 2 有向网 权值 不对称 3 有向图 0 1 不对称 一 无向网 1 思路
  • 使用python的pandas包查询数据库数据导出到excel

    文章目录 前言 1 实现分析 2 实现过程 2 1安装环境 2 3功能逻辑 2 4完整代码 3 总结 前言 前几天接到一个业务的需求 让我把当前数据库里面的结果数据导出到excel中 然后供业务查看 问题是当前结果数据都是列式表 所以需要把
  • 强化学习 reward 曲线的绘制

    每隔一段取一个均值 然后把均值曲线绘制出来 包含全部点的曲线淡化处理 摘自 Z Mou Y Zhang F Gao H Wang T Zhang and Z Han Deep Reinforcement Learning based Thr
  • paddlepaddle安装问题protobuf package to 3.20.x or lower.

    按照官方文档安装paddlepaddle 2 3 0后 进行环境验证时 总是提示如下错误 TypeError Descriptors cannot not be created directly If this call came from
  • 【编程测试题】数字游戏

    题目描述 小易邀请你玩一个数字游戏 小易给你一系列的整数 你们俩使用这些整数玩游戏 每次小易会任意说一个数字出来 然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字 例如 如果 2 1 2 7 是你有的一系列数 小易说的数
  • 【删除列表中最后一条数据遇到的问题】

    项目场景 列表有多页数据 如果最后一页只有一条数据 当删除这条数据时 页码能够改变并且数据正确展示 问题描述 当删除这条数据时 页码可以正确展示 但是数据没有正确显示 handleDelete row const id row userId

随机推荐

  • 服务器 虚拟san,关于服务器 SAN 和 SDS

    注明 本文内容基于VMware VSAN beta版本撰写 请访问http www vmware com products virtual san 获得有关正式版本的更新信息 我很高兴在Wikibon上读到了我的同事Stu Miniman
  • 【微信小程序】项目初始化

    var CSS 函数可以插入一个自定义属性 有时也被称为 CSS 变量 的值 用来代替非自定义 属性中值的任何部分 1 初始化样式与颜色 view text box sizing border box page themColor ad90
  • linux---配置bond方法

    配置bond方法 原始配置文件1 DEVICE eth0 BOOTPROTO dhcp HWADDR 00 0C 29 04 AE 65 IPV6INIT no NM CONTROLLED no ONBOOT yes TYPE Ethern
  • 不用插拔网线鼠标点击自动切换网线和WIFI

    因为之前在zf单位工作 政务内网需要插网线 而访问外网又需要连wifi 切换就需要拔掉网线插上网线很麻烦 旁边老哥教我了一手 bat程序自动切换方法 bat文件代码如下 以下代码的 bat文件执行后会切换到以太网 同时关闭掉wifi和以太网
  • 监听对象中属性变化(一个或多个属性、全部属性)

    一 数据监听器 什么是数据监听器 数据监听器用于监听和响应任何属性和数据自动的变化 从而执行特定的操作 它的作用类似于vue中的watch侦听器 在小程序中 基本语法格式如下 Component observers 字段A 字段B func
  • 积分规划:构建全面会员积分管理系统

    在当今竞争激烈的市场环境中 企业要想保持用户的忠诚度和活跃度 建立一个全面的会员积分管理系统是至关重要的 积分制度不仅可以激励用户参与 还可以增加用户的消费频次和购买金额 本文将深入探讨如何构建全面的会员积分管理系统 以实现更好的私域营销效
  • 消息队列(MQ)

    一 为什么要用消息队列 消息队列的应用场景 应用解耦 异步任务 流量削峰 问题背景 学生向老师请教问题 如果学生A正在向老师请教问题 那么后面的学生依次排队等候 直到轮到自己请教问题 这样的模式会使整个系统的效率较低 学生排队等待时间太久
  • pygame学习笔记

    pygame学习笔记 1 基础知识 参考 1 基础知识 1 设置死循环 持续显示窗口 import pygame import sys pygame init 初始化pygame size 320 240 设置窗口大小 w h screen
  • 数字逻辑触发器(一)

    触发器 一 定义 是一种具有记忆功能的逻辑部件 具有两个稳定的输出状态 用这两个稳定的状态来表示二值信号的0和1 在外界输入信号的激励下 触发器的输出状态会发生改变 二 触发器的种类举例 基本RS触发器 主从触发器 维持阻塞触发器 D触发器
  • 【appium报错】Original error:Could not proxy command to remote server. Original error:socket hang up

    博客链接1 系统自带的应用kill掉appium相关的进程 博客链接2 卸载并重装appium相关安装包 如果上面的方法仍不能解决问题 暴力解决 卸载设备上的appium setting 等appium安装的app 卸载自动化启动的app
  • UncaughtExceptionHandler 获取线程运行时异常

    我们知道线程执行体的方法接口定义为 public void run 因此线程在执行单元中是不允许抛出checked异常的 且线程之间是相对独立的 他们运行在自己的上下文当中 派生它的线程无法直接感知到它在运行时出现的异常信息 为了解决这个问
  • P2084 进制转换

    题目背景 无 题目描述 今天小明学会了进制转换 比如 10101 2 那么它的十进制表示的式子就是 1 2 4 0 2 3 1 2 2 0 2 1 1 2 0 那么请你编程实现 将一个M进制的数N转换成十进制表示的式子 注意 当系数为0时
  • vector 删除元素的几种方法

    vector 删除元素的几种方法 1 利用成员函数pop back 可以删除最后一个元素 2 利用成员函数erase 可以删除由一个iterator指出的元素 3 通过STL中的算法库函数remove 删除指定的元素 与list容器自带的成
  • 鱼眼相机标定

    分享一个最近在复习的一个鱼眼相机标定 这个大佬的链接 因为课题相关 先视觉2D检测再通过标定形成视锥然后再点云目标检测 所以先埋一个坑 刚好2D检测这块做的差不多 不过是Python版本哈 后续肯定要用C 先上一个大佬的鱼眼内参去畸变的链接
  • MavenFor this reason, future Maven versions might no longer support building such malformed projects

    使用IDEA MAVEN clean时提示如下错误 Maven For this reason future Maven versions might no longer support building such malformed pr
  • 查字典(c++)

    思路 判断insert和find insert放入string set find就用count 过程 1 判断insert和find 2 放入set中 3 判断结果 代码 include
  • 清除浮动之双伪元素清除浮动

  • 结构体指针

    结构体指针 当一个指针变量用来指向一个结构体变量时 1 结构体指针变量的值是所指向的结构体变量的起始地址 2 通过结构体指针可以访问结构体变量 定义形式 结构体名 结构体指针变量 也可在定义结构体时 同时定义这个结构体变量 注 1 结构体指
  • 实现从一个类中的实体对象获取所有属性值注入到另一个不同类的实体对象的对应属性中

    背景 由于dao层的可视化对象 bean 跟service层以及controller层的bean对象是分开的 也就是同一业务流水线中 在controller层是跟界面或者接口的交互bean 而到了操作数据库层则用的匹配数据库表的实体bean
  • python wechatsougou_使用Python的requests库模拟登陆微信搜狗,爬取100X10篇微信文章并保存到MySQL...

    自学的python和爬虫技术 使用到Redis MySQL数据库 request请求模块 re Xpath解析模块 dumps loads序列化和反序列化 还可以配合代理池使用 爬取的是https weixin sogou com 网站只能