Python练习【利用线程池爬取电影网站信息】

功能实现

爬取猫眼电影TOP100(http://maoyan.com/board/4?offset=90)
    1). 爬取内容: 电影名称,主演, 上映时间,图片url地址保存到文件中;
    2). 文件名为topMovie.csv;
    3). 记录方式:  电影名称:主演:上映时间:图片url地址:评分;
    4). 并爬取的信息保存在数据库中;
    5). 使用多线程/线城池实现;

编程思路

1.利用多线程分配任务
2.编写单线程的任务实现功能
    (1)获取指定url页面信息。
    (2)从指定信息中匹配所需的信息。
    (3)将获取到的信息分别保存至文件并写入数据库中。

1.利用多线程分配任务

from multiprocessing.pool import ThreadPool
def main():
    # 需要访问10个分页,生成对应的urls列表
    urls = [getPageInfo(‘https://maoyan.com/board/4?offset=%s‘ % i)for i in range(0,91,10)]
    pool = ThreadPool(10)   # 创建线程池对象,上限为10个
    pool.map(getInfoInPage,urls) # 获取信息并保存至文件
    pool.close() # 关闭线程池
    pool.join() # 等待子线程结束

2.单线程任务实现

获取页面信息

# 获取页面信息
def getPageInfo(url):
    pageObj = urlopen(url)
    pageInfo = pageObj.read().decode(‘utf-8‘)
    return pageInfo

保存页面信息到文件moviePage

page = 0 # 定义全局变量便于分页存储
def savePageInfo(pageInfo):
    global page
    page += 1
    with open(‘doc/moviePage%s‘%(page),‘w‘,encoding=‘utf-8‘)as f:
        f.write(pageInfo)
    return pageInfo

建立数据库连接

def connetion():
    return pymysql.connect(
        host=‘localhost‘,
        user=‘root‘,
        password=‘mysql‘,
        database=‘topMovie‘,
        charset=‘utf8‘,
        autocommit=True
    )

从单个页面代码中获取所需数据

def getInfoInPage(page1):
    # 将获取的html源码加工为美味汤(便于获取对应的信息)
    soup = BeautifulSoup(page1, ‘html.parser‘)
        # 遍历单个页面中 class 为 content 的div标签
    for page in soup.find_all(‘div‘, {‘class‘: "content"}):
            # 遍历content节点中的dd标签
        for movie in page.find_all(‘dd‘):
            # 将soup节点转化成字符串
            movieInfo = str(movie)
            # 筛选出需要的信息
            name = movie.find(‘p‘, {‘class‘: "name"}).text # 获取电影名称
            star = re.findall(r‘主演:(.*?)\s‘, movieInfo)[0] # 获取主演
            releaseTime = re.findall(r‘上映时间:(.*?)<‘, movieInfo)[0] # 获取上映时间
            imgUrl = re.findall(r‘"(http.*?)"‘, movieInfo)[0] # 获取宣传图片地址
            score = movie.find(‘p‘, {‘class‘: "score"}).text # 获取评分
            # 电影名称: 主演:上映时间: 图片url地址:评分;
            oneMovieInfo = ‘\n{0}:{1}:{2}:{3}:{4}‘.format(name, star, releaseTime, imgUrl, score)
            # 写入文件
            with open(‘doc/topMovie.csv‘, ‘a+‘, encoding=‘utf-8‘)as f:
                f.write(oneMovieInfo)
            # 单个电影信息存入数据库的sql语句
            insertSql = ‘insert into topmovie(电影名称,主演,上映时间,图片地址,评分) value("{0}","{1}","{2}","{3}","{4}")‘.format(name, star, releaseTime, imgUrl, score)
            lock.acquire() # 加上线程锁,防止多线程公用连接出现问题
            cur.execute(insertSql) # 执行插入语句
            lock.release() # 解锁

多线程公用数据库的安全问题

多线程公用数据库如果不进行安全处理,有时会因为

数据来不及回滚而其他线程进行数据操作,从而导致存储出现问题

可以通过一下几种方式调整:

1.让每个线程拥有自己的连接。

2.利用线程锁来保证单次操作的完整性。

这里采用第二种方式在属性插入语句前后进行加锁和解锁操作
            lock.acquire() # 加上线程锁,防止多线程公用连接出现问题
            cur.execute(insertSql) # 执行插入语句
            lock.release() # 解锁

修改后的主函数

def main():
    with open(‘doc/topMovie.csv‘,‘w‘,encoding=‘utf-8‘)as f:
            f.write(‘电影名称: 主演:上映时间: 图片url地址:评分;‘)
    # 创建连接和游标
    global cur
    global lock
    conn = connetion()
    cur = conn.cursor()
    lock = threading.Lock()
    # 删除并创建一个新表(刷新每次写入的数据)
    dropSql = ‘drop table topMovie;‘
    cur.execute(dropSql)
    createSql = ‘create table topMovie(电影名称 varchar(100),主演 varchar(100),上映时间 varchar(100),图片地址 varchar(100),评分 varchar(100))default charset=utf8‘
    cur.execute(createSql)
    # 生成分页的urls
    urls = [getPageInfo(‘https://maoyan.com/board/4?offset=%s‘ % i)for i in range(0,91,10)]
    # 实现多线程
    pool = ThreadPool(10)
    pool.map(getInfoInPage,urls) # 获取信息并保存至文件
    # 关闭线程池并等待子线程结束
    pool.close()
    pool.join()
    # 关闭游标和连接
    cur.close()
    conn.close()

完整代码

import re
import threading
import time
from multiprocessing.pool import ThreadPool
import pymysql
from bs4 import BeautifulSoup
from urllib.request import urlopen
# 获取页面信息
def getPageInfo(url):
    pageObj = urlopen(url)
    pageInfo = pageObj.read().decode(‘utf-8‘)
    return pageInfo
page = 0
# 保存页面信息到文件moviePage
def savePageInfo(pageInfo):
    global page
    page += 1
    with open(‘doc/moviePage%s‘%(page),‘w‘,encoding=‘utf-8‘)as f:
        f.write(pageInfo)
    return pageInfo

# 计时器
def timeCounter(fun):
    def wrapper(*args,**kwargs):
        startTime = time.time()
        res = fun(*args,**kwargs)
        endTime = time.time()
        print(fun.__name__+‘使用时间为%.2f‘%(endTime-startTime))
        return res
    return wrapper

# 建立数据库连接
def connetion():
    return pymysql.connect(
        host=‘localhost‘,
        user=‘root‘,
        password=‘mysql‘,
        database=‘topMovie‘,
        charset=‘utf8‘,
        autocommit=True
    )

# 从单页源码中获取所需要的信息,并分别存至数据库和文件参数为页面源码(str)
def getInfoInPage(page1):
    soup = BeautifulSoup(page1, ‘html.parser‘)
    for page in soup.find_all(‘div‘, {‘class‘: "content"}):
        for movie in page.find_all(‘dd‘):
            # 将soup节点转化成字符串
            movieInfo = str(movie)
            # 筛选出需要的信息
            name = movie.find(‘p‘, {‘class‘: "name"}).text
            star = re.findall(r‘主演:(.*?)\s‘, movieInfo)[0]
            releaseTime = re.findall(r‘上映时间:(.*?)<‘, movieInfo)[0]
            imgUrl = re.findall(r‘"(http.*?)"‘, movieInfo)[0]
            score = movie.find(‘p‘, {‘class‘: "score"}).text
            # 电影名称: 主演:上映时间: 图片url地址:评分;
            oneMovieInfo = ‘\n{0}:{1}:{2}:{3}:{4}‘.format(name, star, releaseTime, imgUrl, score)
            # 写入文件
            with open(‘doc/topMovie.csv‘, ‘a+‘, encoding=‘utf-8‘)as f:
                f.write(oneMovieInfo)
            # 存入数据库
            insertSql = ‘insert into topmovie(电影名称,主演,上映时间,图片地址,评分) value("{0}","{1}","{2}","{3}","{4}")‘.format(name, star, releaseTime, imgUrl, score)
            lock.acquire()
            cur.execute(insertSql)
            lock.release()
            print(oneMovieInfo)

@timeCounter
def main():
    with open(‘doc/topMovie.csv‘,‘w‘,encoding=‘utf-8‘)as f:
        f.write(‘电影名称: 主演:上映时间: 图片url地址:评分;‘)
    # 创建连接和游标
    conn = connetion()
    global cur
    cur = conn.cursor()
    global lock
    lock = threading.Lock()
    # 创建一个新表
    dropSql = ‘drop table topMovie;‘
    cur.execute(dropSql)
    createSql = ‘create table topMovie(电影名称 varchar(100),主演 varchar(100),上映时间 varchar(100),图片地址 varchar(100),评分 varchar(100))default charset=utf8‘
    cur.execute(createSql)
    urls = [getPageInfo(‘https://maoyan.com/board/4?offset=%s‘ % i)for i in range(0,91,10)]
    pool = ThreadPool(10)
    # pool.map(savePageInfo,urls)
    pool.map(getInfoInPage,urls) # 获取信息并保存至文件
    pool.close()
    pool.join()
    cur.close()
    conn.close()

显示结果

数据库

文件

原文地址:http://blog.51cto.com/13992211/2349069

时间: 2024-10-06 00:40:15

Python练习【利用线程池爬取电影网站信息】的相关文章

梨视频,进程池、线程池爬取

[TOC] 进程池 import requests, re, time from multiprocessing.dummy import Pool import random IpPool = [{'http': '183.147.230.104: 8118'}, {'http': '60.217.64.237: 31923'}, {'http': '221.193.50.166: 8118'}] url = 'https://www.pearvideo.com/category_loadin

Python练习【爬取银行网站信息】

功能实现 爬取所有银行的银行名称和官网地址(如果没有官网就忽略),并写入数据库: 银行链接: http://www.cbrc.gov.cn/chinese/jrjg/index.html 编程思路 1.利用url访问页面并获取页面信息 2.利用正则表达式对页面信息进行筛选,获取我们需要的信息 3.保存至Mysql数据库中 1.获取网页信息并保存至文件 from urllib.request import urlopen # 获取页面信息 def getPageInfo(url): pageInf

python应用:selenium之爬取天眼查信息

inform_table.py 1 # -*-coding:utf8-*- 2 3 from selenium import webdriver 4 from selenium.webdriver.common.proxy import Proxy 5 from selenium.webdriver.common.proxy import ProxyType 6 import time 7 from bs4 import BeautifulSoup 8 9 10 class InformTabl

python爬虫--爬取某网站电影下载地址

前言:因为自己还是python世界的一名小学生,还有很多路要走,所以本文以目的为向导,达到目的即可,对于那些我自己都没弄懂的原理,不做去做过多解释,以免误人子弟,大家可以网上搜索. 友情提示:本代码用到的网址仅供交流学习使用,如有不妥,请联系删除. 背景:自己有台电脑要给老爸用,老爷子喜欢看一些大片,但是家里网络环境不好,就想批量下载一些存到电脑里.但是目前大部分的网站都是这样的, 需要一个个地点进去,才能看到下载地址 如果我要下载100部电影,那肯定手都要点断了,于是便想把这些地址给爬取出来,

Python爬取电影天堂指定电视剧或者电影

1.分析搜索请求 一位高人曾经说过,想爬取数据,要先分析网站 今天我们爬取电影天堂,有好看的美剧我在上面都能找到,算是很全了. 这个网站的广告出奇的多,用过都知道,点一下搜索就会弹出个窗口,伴随着滑稽的音乐,贪玩蓝月? 通过python,我们可以避免广告,直接拿到我们要的东西 我用的是火狐浏览器,按F12打开开发者工具,选择网络 按照正常的操作顺序,其实python就是在模拟人进行一些网页操作,我们只不过通过python解放自己的双手 在搜索框输入“傲骨贤妻”,当然你输入其他的电视剧名称也可以,

python利用selenium+requests+beautifulsoup爬取12306火车票信息

在高速发展的时代.乘车出远门是必不可少的,有些查询信息是要收费的.这里打造免费获取火车票信息 想要爬取12306火车票信息,访问12306官方网站,输入出发地,目的地  ,时间  之后点击确定,这是我们打开谷歌浏览器开发者模式找到   https://kyfw.12306.cn/otn/resources/js/framework/station_name.js    这里包含了所有城市的信息和所有城市的缩写字母.想要获取火车票信息  https://kyfw.12306.cn/otn/left

Python的并发并行[4] -&gt; 并发 -&gt; 利用线程池启动线程

利用线程池启动线程 submit与map启动线程 利用两种方式分别启动线程,同时利用with上下文管理来对线程池进行控制 1 from concurrent.futures import ThreadPoolExecutor as tpe 2 from concurrent.futures import ProcessPoolExecutor as ppe 3 from time import ctime, sleep 4 from random import randint 5 6 def f

Python爬虫实战二之爬取百度贴吧帖子

大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 前言 亲爱的们,教程比较旧了,百度贴吧页面可能改版,可能代码不好使,八成是正则表达式那儿匹配不到了,请更改一下正则,当然最主要的还是帮助大家理解思路. 2016/12/2 本篇目标 1.对百度贴吧的任意帖子进行抓取 2.指定是否只抓取楼主发帖内容 3.将抓取到的内容分析并保存到文件 1.URL格式的确定 首先,我们先观察一下百度贴吧的任意一个帖子. 比如:ht

Python3爬取电影信息:调用API

实验室这段时间要采集电影的信息,给出了一个很大的数据集,数据集包含了4000多个电影名,需要我写一个爬虫来爬取电影名对应的电影信息. 其实在实际运作中,根本就不需要爬虫,只需要一点简单的Python基础就可以了. 前置需求: Python3语法基础 HTTP网络基础 =================================== 第一步,确定API的提供方.IMDb是最大的电影数据库,与其相对的,有一个OMDb的网站提供了API供使用.这家网站的API非常友好,易于使用. http://