基于搜狗微信的seleinum公众号爬虫

Posted by Futari on 2021-10-14
Estimated Reading Time 6 Minutes
Words 1.4k In Total
Viewed Times

1.首先导入所需要的库,这里用到的主要是seleinum

请仔细查看代码注释

1
2
3
4
5
6
7
8
9
10
from selenium import webdriver  # 从自动化库里导入这个模块
from selenium.webdriver.support.ui import WebDriverWait # 从模块导入显示等待(隐式,强制)
from selenium.webdriver.support import \
expected_conditions as EC # 导入模块()可以对网页上元素,弹窗是否存在,可点击等等进行判断,一般用于断言或与WebDriverWait配合使用。
from selenium.webdriver.common.by import By # By是selenium中内置的一个class,在这个class中有各种方法来定位元素(定位器,用于css,xpath )
import json
import csv
import requests
from lxml import etree
import time

2.创建浏览器对象来以便进行浏览器操作

1
2
3
4
5
6
7
8
9
10
# 声明一个谷歌浏览器的驱动器
browser = webdriver.Chrome(executable_path='./chromedriver')#打开chrome和驱动(webdriver模块放一个文件,不写路径)(自动化库到驱动到浏览器)
# url网址
url = 'https://weixin.sogou.com/'
# 请求该网址
browser.get(url)#get方法打开网址
# 声明一个列表存储字典
data_list = []
#声明一个全局变量用来定义页数
page = 0

下面加入请求头信息,并完成登陆操作(登录之后才可以进行翻页和其它操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def start_spiders():  # 定位是关键,找到输入框等等,选择元素,通过特征
headers = {
'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'
} # 添加为自己的
# 找到输入框id
query = browser.find_element_by_id('query') # 和下方定位同理
keyword = input('输入:')
query.send_keys(keyword) # query是一个element对象,用send_keys方法输入字符串
# 找到搜索按钮
swz = browser.find_element_by_class_name('swz') # 找到搜索按钮,找到这个swz标签(classname是这个,如果name或者id唯一用name,id找也行(找特征))
swz.click()
# 找到登陆按钮并点击

top_login = browser.find_element_by_id('top_login')
top_login.click()#一步一步模拟
# 显示等待是否登陆成功
WebDriverWait(browser, 1000).until( #对象是brower,就是驱动器,最大等待1000时间
EC.presence_of_all_elements_located(
(By.CLASS_NAME, 'yh')#(刷新,直到登陆成功找到class为yh,就成功了,大家可以从源代码里找到这个标签,同时返回布尔数)
)
)
print('登陆成功')


3.用Xpath来获取获取所需要的数据,其中题目坐着等信息在搜索的预览界面就可以进行爬取,文章的具体内容需要进入到文章链接中进行爬取

在末尾检测“下一页”的标签,如果存在就需要对其进行点击来完成翻页操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    num = 0
while True:
# 找到所有的li标签(在开发者里面找到相应的元素(由标签名等等)List是列表)
#lis = browser.find_elements_by_xpath('//ul[@class="news-list"]/li') # 从根目录找到class为。。的ul元素
# 找到下一页的按钮
# 遍历列表,存到字典里去

for a in range(9):
try:
# 题目
lis = browser.find_elements_by_xpath('//ul[@class="news-list"]/li')

title = lis[a].find_element_by_xpath('.//h3').text

# 作者
author = lis[a].find_element_by_class_name('account').text
# 时间
datetime = lis[a].find_element_by_class_name('s2').text
# 文章摘要
content = lis[a].find_element_by_class_name('txt-info').text
# 文章链接
href = lis[a].find_element_by_xpath('.//h3/a').get_attribute('href')
# 学号
id = '20190200514'
browser.get(href)

time.sleep(0.5)
text_list = browser.find_elements_by_xpath('/html/body/div[1]/div[2]/div[1]/div/div[1]/div[3]/section')
# text_list = browser.find_elements_by_xpath('/html/body/div[1]/div[2]/div[1]/div/div[1]/div[3]/section[4]/span') # 从根目录找到class为。。的ul元素
texts = ""
for i in text_list:
texts += (i.text)

print(texts)
# for text in text_list:
# text2 = text.text
# print(text2)
# texts += text2

# 声明一个字典存储数据

data_dict = {}
data_dict['text'] = texts
data_dict['title'] = title
data_dict['author'] = author
data_dict['datetime'] = datetime
data_dict['content'] = content
data_dict['href'] = href
data_dict['user_id'] = id
data_dict['key_words'] = keyword

# print(data_dict)

data_list.append(data_dict) # 把遍历出的数据添加到列表末尾
# 如果找不到下一页按钮就抛出异常并退出循环
browser.back()
except IndexError as i:
print("爬虫被检测,请手动输入验证码:")
time.sleep(100)
continue
#下面进行翻页操作

try:
sogou_next = browser.find_element_by_id('sogou_next')
# 如果下一页按钮存在就继续
sogou_next.click()
num = num + 1
if num > page: #修改循环来控制爬取的页数
break
except Exception as e:
break

注意:

由于搜狗微信的对于同一IP访问有一定的0数量限制,所以每天在爬取一定量的数据之后,会弹出验证码身份检验,本程序设置了100秒的输入时间,需要调用者手动输入验证码来进行验证,同时也可以在爬虫受限之后更改代理。
所以后续代码的改进方向为:
1.设置IP池,通过更换ip来从根本上解决验证问题(来源需要自己找,可以找网上的免费代理)
2.连接验证码打码平台,由于本程序是在爬取一定量数据之后才会触发检测,所以触发检测的机会较少,打码的必要性不是很大。

4. 最后编写执行程序代码块(文件输出方式可选json和csv输出)

1
2
3
4
5
6
7
8
9
10
11
12
def main():
start_spiders()

if __name__ == '__main__':
main()
# 退出浏览器
browser.quit()
print(data_list)
# 将数据存储到json文件中
with open('data_json.json', 'a+', encoding='utf-8') as f:
json.dump(data_list, f, ensure_ascii=False, indent=4)#用dump把python数据结构转换为json类型
print('json文件写入完成')

也可以存储为CSV文件

1
2
3
4
5
6
7
8
9
10
11
12
# 将数据存入csv文件中
# 表头
# csv_title = data_list[0].keys()#返回一个字典的【0】键
# with open('data_csv.csv', 'w', encoding='utf-8', newline='') as f:
# writer = csv.writer(f)
# # 写入表头
# writer.writerow(csv_title)
# # 批量写入表
# for row in data_list:
# writer.writerow(row.values())
# print('csv文件写入完成')


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !