爬虫 自动化工具-mongo-多线程爬虫_broeser-程序员宅基地

技术标签: 爬虫自动化  多线程  MongoDB  自动化  

一、selenium框架

1、selenium介绍

# 介绍: 
1.selenium是一个web自动化测试用的框架. 程序员可以通过代码实现对浏览器的控制, 
比如打开网页, 点 击网页中的元素, 实现鼠标滚动等操作. 
2.它支持多款浏览器, 如谷歌浏览器, 火狐浏览器等等, 当然也支持无头浏览器. 
# 目的: 
在爬取数据的过程中, 经常遇到动态数据加载, 一般动态数据加载有两种,
 一种通过ajax请求加载数据, 另 一种通过js代码加载动态数据. 
 selenium可以模拟人操作真实浏览器, 获取加载完成的页面数据

ajax:
    url有规律且未加密, 直接构建url连接请求 
    url加密过无法破解规律 --> selenium 
js动态数据加载 --> selenium

2、selenium安装

三要素: 浏览器, 驱动程序, selenium框架 
    浏览器: 推荐谷歌浏览器, 标准稳定版本 驱动程序:
    http://chromedriver.storage.googleapis.com/index.html pip install selenium 
                
# 测试: 
from selenium import webdriver 
# 将驱动放在脚本所在的文件夹 
browser = webdriver.Chrome('./chromedriver.exe') 
browser.get('https://www.baidu.com')

3、selenium常用操作

# 实例化浏览器对象: 
from selenium import webdriver 
browser = webdriver.Chrome('driverpath') 

# 发送get请求: 
browser.get('https://www.baidu.com')
browser.get('https://image.baidu.com')
# 获取网页的数据: browser.page_source ---> str类型 
# 获取页面元素: 
find_element_by_id:根据元素的id 
find_element_by_name:根据元素的name属性 find_element_by_xpath:根据xpath表达式 find_element_by_class_name:根据class的值 find_element_by_css_selector:根据css选择器
                
# 节点交互操作: 
click(): 点击 
send_keys(): 输入内容 
clear(): 清空操作 
execute_script(js): 执行指定的js代码 
# JS代码: window.scrollTo(0, document.body.scrollHeight)可以模拟鼠标滚动一屏高度 
quit(): 退出浏览器 


# frame 
# 若爬取一个页面,需观察如果有两个HTML(一个父HTML,一个子HTML),所需内容在子HTML中,则需要switch_to.frame('frameid') 转至子页面继续操作

switch_to.frame('frameid')            

4、用自动化模拟QQ,微博,登录

from selenium import webdriver
import time
# 实例化浏览器对象
browser = webdriver.Chrome('./chromedriver.exe')
# 打开qq空间登陆页面
browser.get('https://qzone.qq.com/')
time.sleep(1)
# 转至frame子页面
browser.switch_to.frame('login_frame')
# 获取密码登陆选项并点击
a_tag = browser.find_element_by_id('switcher_plogin')
a_tag.click()
time.sleep(1)
# 获取账号输入框并输入账号
browser.find_element_by_id('u').clear()
user = browser.find_element_by_id('u')
user.send_keys('1816668038')
time.sleep(1)
# 获取密码输入框并输入密码
browser.find_element_by_id('p').clear()
pwd = browser.find_element_by_id('p')
pwd.send_keys('1971628197192liu')
time.sleep(1)
# 获取登陆按钮并单击
button = browser.find_element_by_id('login_button')
button.click()




'''
微博模拟登陆
'''''
# import requests,time
# from selenium import webdriver
# broeser = webdriver.Chrome('./chromedriver.exe')
# broeser.get('https://weibo.com/login.php')
#
# input_tag = broeser.find_element_by_id('loginname')
# input_tag.clear()
# input_tag.send_keys('15135544556')
# time.sleep(3)
# input_tag_pwd = broeser.find_element_by_xpath('//div[@class="info_list password"]/div[@class="input_wrap"]/input')
# input_tag_pwd.clear()
# input_tag_pwd.send_keys('123456789liu')
# time.sleep(3)
# button_tag = broeser.find_element_by_xpath('//div[@class="W_login_form"]/div[@class="info_list login_btn"]/a')
# button_tag.click()

5、图片懒加载

'''
网址 http://sc.chinaz.com/tupian/   站长素材
图片懒加载
'''''

import requests
from lxml import etree
url = 'http://sc.chinaz.com/tupian/bingxueshijie.html'
headers = {
    
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
}
res = requests.get(url=url,headers=headers)
tree = etree.HTML(res.text)
#src2的位置,在必要的时候可以把值赋给src----懒加载核心
ret = tree.xpath('//div[@id="container"]/div/div/a/img/@src2')

for i in ret:
    comment = requests.get(url=i,headers=headers).content
    name = i.split('/')[-1]
    with open('./image/%s'% name,'wb') as f:
        f.write(comment)

二、Mongo数据库

1、mongo的安装

(将安装目录下的bin目录添加到系统环境变量中)
# mongo的配置: 
1.创建数据库文件及日志文件目录, 并将目录写入配置文件 
2.在系统终端执行以下命令: mongod --bind_ip 127.0.0.1 --logpath "D:\Professional\MongoDB\log\mongodb.log" - -logappend --dbpath "D:\Professional\MongoDB\db" --port 27017 --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install 3.将MongoDB服务设为开机自启

2、mongo数据库操作

//常用操作: 
// 1.查看数据库 
show dbs 
// 2.创建并使用数据库 
use tst 
// 3.查看当前工作的数据库 
db
// 4.创建集合并插入一条数据 
db.goods.insert({
    "name":"辣条", "price":0.5}) 
// 5.查看所有表 
show tables 
// 6.查询表中所有数据 
db.goods.find() 
// 7.删除表操作
db.goods.drop() 
// 8.删除数据库 
db.dropDatabase()
--------------------------------------------------------------------------

# 增加数据操作: 
db.tablename.insert({
    dict}) 
# 示例: 增加数据操作: 
db.goods.insert({
    "name":"辣条", "price":0.5}) 
db.goods.insert({
    "name":"辣条", "price":1}) 
db.goods.insert({
    "name":"干脆面", "price":0.5}) db.goods.insertOne({
    "name":"单身狗粮", "price":4.5}) db.goods.insertMany([{
    "name":"小洋人", "price":3.5}, {
    "name":"麦香鸡块", "price":5.5}])

----------------------------------------------------------------------------
# 查询数据操作:
//1、查看数据库   show dbs只能查看有数据的数据库
show dbs

//2、创建并使用数据库
use a1903

//3、查看当前正在工作的数据库
db

//4、插入数据
db.student.insert({
    'name':'胡歌','age':30})

db.student.insertOne([{
    'name':'胡歌'}])
db.student.insertMany([{
    'name':'鹿晗','age':27},{
    'name':'关晓彤','age':23}])
db.student.insertMany([{
    'name':'刘国鑫','age':22},{
    'name':'庞明哲','age':20}])
//5、查询表中数据
db.student.find()
db.student.find().limit(3)


// 按条件查询
// 1.等值查询
db.student.find({
    'name':'晓彤'})

// 2.非等值查询:大于$gt(great than),小于$lt(little than),大于等于$gte(great than equal),小于等于$lte(little than equal),不等于$ne
db.student.find({
    age:{
    $gt:23}})
db.student.find({
    'age':{
    $lt:23}})
db.student.find({
    'age':{
    $ne:21}})

// 3. andor 
db.student.find({
    'name':'晓彤','age':21})
db.student.find({
    $or[{
    'name':'晓彤'},{
    'age':27}]})
  
// and  a 与 b之间
db.student.find({
    'age':{
    $gt:20},'age':{
    $lte:27}})
db.student.find({
    'age':{
    $gt:20,$lte:27}})
 
db.student.find({
    $or:[{
    'age':{
    $lt:23}},{
    'age':{
    $gt:25}}]})

// 更新数据操作
db.student.update({
    'name':'晓彤'},{
    $set{
    'age':18}})

//6、查看表
show tables

//7、删除表
db.student.drop()

//8、删除库
db.dropDatabase()

//9、指定删除
db.student.remove({
    'name':''})
-----------------------------------------------------------------------------
# 更新数据操作: 
db.table.update({
    定位字典}, {
    指定修改的键值}) 
# 示例:更新数据操作: 
	db.goods.update({
    "price":0.5},{
    $set:{
    "price":5}}) 
		# 参数中的第一个字典用于定位要修改的数据 
		# 参数中的第二个字典是指定要更新已定位的数据 
		# 第二个参数中的字典是指定要将哪个字段的修改为什么
----------------------------------------------------------------------------
# 删除数据操作: 
db.tablename.remove({
    定位字典})
# 示例:删除数据操作: 
db.goods.remove({
    "price":5})

3、Python与Mongo交互

# 导入模块 如果没安装先安装  pip install pymongo
import pymongo 
# 连接MongoDB数据库 
conn = pymongo.MongoClient('localhost', 27017) 
# 创建库或连接数据库
db = conn.goods 
# 创建表或连接表
table = db.snacks 
# 数据操作: 插入数据 
table.insert(dict) 
table.insert_one(dict)  ******************在py文件中看具体清空使用
table.insert_many([dict1, dict2, dict3]) 
# 数据操作: 查询数据 
table.find_one({
    dict}) 
# 返回一个字典形式数据 
table.find() 
# 返回一个mongo对象, 需要使用for循环遍历取值 
table.find({
    dict}) # 同上

三、多线程爬虫

1、并发,并行的理解

# 并发:同一时间段同时运行
# 并行:同一时刻同时运行
# 时间片轮转法:10个视屏不间断播放,是并发运行,但给人的错觉是并行
# 高IO密集(比如在一个刚运行的代码前就有设置的)  阻塞,cup算法密集

2、实现多线程爬虫

***用多线程爬虫,最重要的就是传参,获取数据,思路********
import threading,requests
# 导入多线程锁机制
from threading import Lock
# 导入线程队列
from queue import Queue
from lxml import etree
import pymongo
# 爬虫类,负责采集数据的
class CrawThread(threading.Thread):
    # 初始化init方法,接收参数
    def __init__(self,name,pageQueue,dataQueue):
        super().__init__()
        self.name = name
        self.pageQueue = pageQueue
        self.headers = {
    
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
        }
        self.dataQueue = dataQueue

    # 执行run方法,在def函数调用时执行
    def run(self):
        # 爬取的页数不确定,格式化输出
        base_url = 'https://www.xiaohua.com/duanzi?page=%s'
        while 1:
            try:
                print('开始url')
                # 传参时要抓取几页的数据已准备好直接get获取,block为False用try捕获异常抓取结束,就终止循环
                page = self.pageQueue.get(block=False)
                # 将页码拼接
                url = base_url % page
                res = requests.get(url=url,headers=self.headers)
                self.dataQueue.put(res.text)
                print('URL完成')
            except:
                break

# 数据解析类
class Parse(threading.Thread):
    def __init__(self,name,dataQueue,look):
        super().__init__()
        self.name = name
        self.dataQueue = dataQueue
        self.look = look

    def run(self):
        while 1:
            try:
                html = self.dataQueue.get(block=False)
                print('正在解析')
                # 把获取的HTML的文本放在下一个函数的里进行操作
                self.parserver(html)
                print('解析完毕')
            except:
                break
                
    def parserver(self,html):
        # 解析
        tree = etree.HTML(html)
        div_list = tree.xpath('//div[@class="one-cont"]')
        for div in div_list:
            item = {
    }
            author = div.xpath('./div/div/a/i/text()')
            item['author'] = author[0]
            # 上锁
            with self.look:
                self.save(item)

    def save(self,item):
        # 连接MongoDB数据库
        conn = pymongo.MongoClient('localhost',27017)
        db = conn.XIAOHUA
        table = db.xh
        table.insert_one(item)

def main():
    # 存放URl----实例化队列对象
    pageQueue = Queue()
    for j in range(1,11):
        # put将所需要的数据存入
        pageQueue.put(j)
    #存放脏数据
    dataQueue = Queue()
    crawlist = ['爬虫1号','爬虫2号','爬虫3号']
    # join等待进程以防有一个进程死掉
    for i in crawlist:
        c = CrawThread(i,pageQueue,dataQueue)
        c.start()
        c.join()
    # 实例化机制锁对象
    look = Lock()
    jiexi = ['解析1号','解析2号','解析3号',]
    for var2 in jiexi:
        cc = Parse(var2,dataQueue,look)
        cc.start()
        # 等待其他线程执行,以防提早结束其他线程死掉
        cc.join()


if __name__ == '__main__':
    main()
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liuguoxin_97/article/details/102698108

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签