Python-爬虫 下载天涯论坛帖子

请添加图片描述
为了爬取的高效性,实现的过程中我利用了python的threading模块,下面是threads.py模块,定义了下载解析页面的线程,下载图片的线程以及线程池

import threading
import urllib2
import Queue
import re

thread_lock = threading.RLock()

#下载页面的一个函数,header中没有任何内容也可以顺利的下载,就省去了
def download_page(html_url):
try:
req = urllib2.Request(html_url)
response = urllib2.urlopen(req)
page = response.read()
return page
except Exception:
print ‘download %s failed’ % html_url
return None

#下载图片的一个方法,和上面的函数很像,只不过添加了一个文件头
#因为在测试的过程中发现天涯对于没有如下文件头的图片链接是不会返回正确的图片的
def download_image(image_url, referer):
try:
req = urllib2.Request(image_url)
req.add_header(‘Host’, ‘img3.laibafile.cn’)
req.add_header(‘User-Agent’, ‘Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0’)
req.add_header(‘Accept’, ‘image/png,image/*;q=0.8,*/*;q=0.5’)
req.add_header(‘Accept-Language’, ‘zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3’)
req.add_header(‘Referer’, referer)
req.add_header(‘Origin’, ‘http://bbs.tianya.cn’)
req.add_header(‘Connection’, ‘keep-alive’)
response = urllib2.urlopen(req)
image = response.read()
return image
except Exception:
print ‘download %s failed’ % image_url
return None

#下载和解析一个页面的线程类
class download_html_page(threading.Thread):
#name:线程的名字
#page_range:用户输入的页面范围
#page_contents:解析之后楼主的内容
#img_urls:解析之后楼主贴的图的链接
#html_url:输入的页面url
#first_page:第一次已经下载好的页面,主要是考虑效率,不重复下载
def __init__(self, name, page_range, page_contents, img_urls, html_url, first_page):
threading.Thread.__init__(self)
self.name = name
self.page_range = page_range
self.page_contents = page_contents
self.img_urls = img_urls

    self.html\_url = html\_url  
    self.first\_page = first\_page  
  
#判断是不是楼主的内容  
def is\_louzhu(self, s):  
    result = re.search(r'<!-- <div class="host-ico">(.\*?)</div> -->', s, re.S)  
    return (result is not None)  

#获得页面里属于楼主图片的url  
def get\_img\_url(self, s, page\_url):  
    #判断是不是楼主给其他用户的评论,如果是的话,直接过滤掉(本人从不看评论)  
    is\_louzhu\_answer = re.search(r'-{15,}<br>', s, re.S)  
    if is\_louzhu\_answer is None:  
        imgurl = re.findall(r'<img.\*?original="(?P<imgurl>.\*?)".\*?/><br>', s, flags = re.S)  

        url\_path = \[\]  
        for one\_url in imgurl:  
            self.img\_urls.put(one\_url + '|' + page\_url)  
            path = re.search('\\w+\\.jpg', one\_url).group(0)  
            url\_path.append('img/' + path)  

        segments = re.split(r'<img .\*?/><br>', s.strip())  
        content = segments\[0\].strip()  
        for i in range(len(url\_path)):  
            content += '\\n<img src = "' + url\_path\[i\] + '" />\\n<br>'  
            content += segments\[i+1\].strip()  
        return content  

#解析夜歌页面  
def parse\_page(self, html\_page, page\_url):  
    html\_page.decode('utf-8')  
    Items = re.findall(r'<div class="atl-content">(?P<islouzhu>.+?)<div class="bbs-content.\*?">(?P<content>.+?)</div>', html\_page, re.S)  
    page\_content = ''  

    for item in Items:  
        if self.is\_louzhu(item\[0\]):  
            one\_div = self.get\_img\_url(item\[1\], page\_url)  
            if one\_div is not None:  
                page\_content += one\_div  
    return page\_content  

def run(self):  
    while self.page\_range.qsize() > 0:  
        page\_number = self.page\_range.get()  
        page\_url = re.sub('-(\\d+?)\\.shtml', '-' + str(page\_number) + '.shtml', self.html\_url)  

        page\_content = ''  
        print 'thread %s is downloading %s' % (self.name, page\_url)  
        if page\_url == self.html\_url:  
            page\_content = self.parse\_page(self.first\_page, page\_url)  
        else:  
            page = download\_page(page\_url)  
            if page is not None:  
                page\_content = self.parse\_page(page, page\_url)  
        #thread\_lock.acquire()  
        #self.page\_contents\[page\_number\] = page\_content  
        #thread\_lock.release()  
        self.page\_contents.put(page\_content, page\_number)  
    self.img\_urls.put('finished')  

#下载图片的线程
class fetch_img(threading.Thread):
def __init__(self, name, img_urls, download_img):
threading.Thread.__init__(self)
self.name = name
self.img_urls = img_urls
self.download_img = download_img

def run(self):  
    while True:  
        message = self.img\_urls.get().split('|')  
        img\_url = message\[0\]  
        if img\_url == 'finished':  
            self.img\_urls.put('finished')  
            break  
        else:  
            thread\_lock.acquire()  
            if img\_url in self.download\_img:  
                thread\_lock.release()  
                continue  
            else:  
                thread\_lock.release()  
                print 'fetching image %s' % img\_url  
                referer = message\[1\]  
                image = download\_image(img\_url, referer)  
              
                image\_name = re.search('\\w+\\.jpg', img\_url).group(0)  
                with open(r'img\\%s' % image\_name, 'wb') as img:  
                    img.write(image)  
                thread\_lock.acquire()  
                self.download\_img.add(img\_url)  
                thread\_lock.release()  

#定义了一个线程池
class thread_pool:
def __init__(self, page_range, page_contents, html_url, first_page):
self.page_range = page_range
self.page_contents = page_contents
self.img_urls = Queue.Queue()
self.html_url = html_url
self.first_page = first_page
self.download_img = set()

    self.page\_thread\_pool = \[\]  
    self.image\_thread\_pool = \[\]  
      
def build\_thread(self, page, image):  
    for i in range(page):  
        t = download\_html\_page('page thread%d' % i, self.page\_range, self.page\_contents,  
                                self.img\_urls, self.html\_url, self.first\_page)  
        self.page\_thread\_pool.append(t)  
    for i in range(image):  
        t = fetch\_img('image thread%d' % i, self.img\_urls, self.download\_img)  
        self.image\_thread\_pool.append(t)  
      
def all\_start(self):  
    for t in self.page\_thread\_pool:  
        t.start()  
    for t in self.image\_thread\_pool:  
        t.start()  
  
def all\_join(self):  
    for t in self.page\_thread\_pool:  
        t.join()  
    for t in self.image\_thread\_pool:  
        t.join()  

下面是主线程的代码:

# -*- coding: utf-8 -*-
import re
import Queue
import threads

if __name__ == ‘__main__’:
html_url = raw_input('enter the url: ')
html_page = threads.download_page(html_url)

max\_page = 0  
title = ''  
if html\_page is not None:  
    search\_title = re.search(r'<span class="s\_title"><span style="\\S+?">(?P<title>.+?)</span></span>', html\_page, re.S)  
    title = search\_title.groupdict()\['title'\]  

    search\_page = re.findall(r'<a href="/post-\\S+?-\\d+?-(?P<page>\\d+?)\\.shtml">(?P=page)</a>', html\_page, re.S)  
    for page\_number in search\_page:  
        page\_number = int(page\_number)  
        if page\_number > max\_page:  
            max\_page = page\_number  
              
print 'title:%s' % title  
print 'max page number: %s' % max\_page  
  
start\_page = 0  
while start\_page < 1 or start\_page > max\_page:  
    start\_page = input('input the start page number:')  
      
end\_page = 0  
while end\_page < start\_page or end\_page > max\_page:  
    end\_page = input('input the end page number:')  
      
page\_range = Queue.Queue()  
for i in range(start\_page, end\_page + 1):  
    page\_range.put(i)  

page\_contents = {}  
thread\_pool = threads.thread\_pool(page\_range, page\_contents, html\_url, html\_page)  
thread\_pool.build\_thread(1, 1)  
thread\_pool.all\_start()  
thread\_pool.all\_join()  

本文仅作项目练习,且勿商用!!!

由于文章篇幅有限,文档资料内容较多,需要这些文档的朋友,可以加小助手微信免费获取,【保证100%免费】,中国人不骗中国人。
请添加图片描述
全套Python学习资料分享:
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述
在这里插入图片描述
二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,还有环境配置的教程,给大家节省了很多时间。
在这里插入图片描述
三、全套PDF电子书
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
在这里插入图片描述
四、入门学习视频全套
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
在这里插入图片描述
在这里插入图片描述
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述
在这里插入图片描述
今天就分享到这里啦,感谢大家收看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/744644.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

宝塔计划任务调用node程序时,log4js日志保存本地位置会发生变化

接我上一篇文章的情况 超简单的nodejs使用log4js保存日志到本地&#xff08;可直接复制使用&#xff09;-CSDN博客 原本应当保存在node项目目录下的日志文件&#xff0c;如果使用宝塔的计划任务来定时执行的话&#xff0c;日志保存路径会发生变化到如下图的位置&#xff1a; 如…

JFrame和JScrollPanel布局初步使用

还不是很了解&#xff0c;做了几个程序&#xff1b; import java.awt.Container; import java.awt.Color; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.border.EmptyBorder;public class pa1 {public static void main(String[] agrs){JF…

AWS在国内的持续受欢迎:探究背后的原因

亚马逊云&#xff08;AWS&#xff09;作为全球领先的云计算服务提供商&#xff0c;在国内市场仍然保持着强劲的竞争力和广泛的用户群。尽管国内也有一些本土云计算服务提供商的崛起&#xff0c;但AWS在国内仍然有大量的用户在使用。我们九河云&#xff0c;一直致力AWS云相关服务…

如何使用 Swift 中的 GraphQL

文章目录 前言基础知识ApolloGraphQL结论前言 我一直在分享关于类型安全和在 Swift 中构建健壮 API 的更多内容。今天,我想继续探讨类型安全的话题,介绍 GraphQL。GraphQL 是一种用于 API 的查询语言。本周,我们将讨论 GraphQL 的好处,并学习如何在 Swift 中使用它。 基础…

面试-JMM的内存可见性

1.JAVA内存模型 分析&#xff1a; 由于JVM运行程序的实体是线程&#xff0c;而每个线程创建时&#xff0c;JVM都会 为其创建一个工作内存(栈空间),用于存储线程私有的数据。而java内存模型中规定所有变量都存储在主内存中。主内存是共享内存区域&#xff0c;所有线程都可以访问…

国密SSL证书提升网络安全

随着数字化时代的到来&#xff0c;网络安全已经成为全球关注的焦点。在这种背景下&#xff0c;SSL证书作为保护数据传输安全的重要工具&#xff0c;其重要性日益凸显。 数字证书产品有以下几种类别&#xff1a; 单域名SSL证书&#xff1a;为单一网站提供安全保护。 多域名SS…

C++ ─── vector的实现

知识点&#xff1a; ① 因为vector是模版&#xff0c;所以声明和定义都放在.h中&#xff0c;防止出现编译错误 .h不会被编译&#xff0c;在预处理中.h在.cpp中展开所以在编译时只有.cpp 而 .cpp顺序编译&#xff0c;只会进行向上查找&#xff0c;因此至少有函数的声明。 ②memc…

【JavaEE】浅谈线程(二)

线程 线程的常见属性 线程属性可以通过下面的表格查看。 •ID 是线程的唯⼀标识&#xff0c;不同线程不会重复 • 名称是各种调试⼯具⽤到&#xff08;如jconsoloe&#xff09; • 状态表示线程当前所处的⼀个情况&#xff0c;下⾯我们会进⼀步说明 • 优先级高的线程理论上来…

报道 | 2024年7月-2024年9月国际运筹优化会议汇总

封面图来源&#xff1a; https://www.pexels.com/zh-cn/photo/1181406/ 2024年7月-2024年9月召开会议汇总&#xff1a; 2024 INFORMS Advances in Decision Analysis Conference (ADA) Location: Finland Important Dates: Conference: July 10-12, 2024 Details:https://w…

【学习】科大睿智解读ITSS认证中咨询机构的作用

企业拥有ITSS认证这不仅将为企业开拓商机&#xff0c;提升竞争力&#xff0c;还能促使企业改进内部运维流程&#xff0c;提高服务质量&#xff0c;为客户提供更优质的IT运维支持。在ITSS认证中&#xff0c;咨询机构扮演着重要的角色&#xff0c;其主要作用包括以下几个方面&…

【服务器】磁盘满载--docker 的日志文件太大造成满载

一.背景 早上过来测试反馈服务器都宕机了,访问不了。一看服务器磁盘都已经满了。所以开始清磁盘数据。 二.解决 主要查看下面目录情况: /home/libe/docker /containers /volumes /overlay21.查看磁盘情况 df -h/ du -a|sort -rn|…

前端开发的工厂设计模式

在前端开发中&#xff0c;工厂设计模式&#xff08;Factory Pattern&#xff09;是一种非常有用的设计模式&#xff0c;能够帮助我们在创建对象时减少代码的重复性和复杂性。 一、工厂设计模式概述 工厂设计模式是一种创建型设计模式&#xff0c;主要目的是定义一个用于创建对…

【PL理论深化】(6) Ocaml 语言: 函数 | 匿名函数 | 函数可以接受多个参数 | OCaml 是一种将函数视为 first-class 的语言

&#x1f4ac; 写在前面&#xff1a;本章我们继续介绍如何使用 OCaml 进行函数式编程。介绍如何使用 let 定义函数&#xff0c;讲解匿名函数&#xff0c;函数可以接受多个参数&#xff0c;以及讨论 OCaml 将函数视为 first-class。 目录 0x00 函数 0x01 匿名函数&#xff08…

【C语言】--常见类型和概念

❤️个人主页: 起名字真南 &#x1f495;个人专栏:【数据结构初阶】 【C语言】 目录 第一个C语言程序main函数printf函数库函数关键字字符和ASCII码字符串和\0转义字符 第一个C语言程序 #include<stdio.h> int main() {printf("Hello World\n");return 0; }ma…

【神经网络】CNN网络:深入理解卷积神经网络

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&#xff01; CNN网络&#xff1a;深入理解…

springboot集成达梦数据库,打包后,tomcat中启动报错

背景&#xff1a;springboot集成达梦数据库8&#xff0c;在工具idea中正常使用&#xff0c;但是打包后&#xff0c;无法启动&#xff0c;报错 pom引入的依赖 但是这种情况&#xff0c;只有在idea中启动没问题的解决方法 需要修改引入的依赖&#xff0c;再次打包就可以 <d…

PatchMixer:一种用于长时间序列预测的Patch混合架构

前言 《PatchMixer: A Patch-Mixing Architecture for Long-Term Time Series Forecasting》原文地址&#xff0c;Github开源代码地址GitHub项目地址Some-Paper-CN。本项目是译者在学习长时间序列预测、CV、NLP和机器学习过程中精读的一些论文&#xff0c;并对其进行了中文翻译…

苹果电脑压缩pdf文件,苹果电脑里如何压缩pdf文件

压缩PDF文件是现代办公和日常生活中经常需要处理的一项任务&#xff0c;无论是为了节省存储空间、方便网络传输&#xff0c;还是为了在移动设备上更流畅地阅读文档&#xff0c;学会有效地压缩PDF都显得尤为重要。在本文中&#xff0c;我们将详细探讨压缩PDF的方法&#xff0c;从…

Mac安装多版本node

Mac下使用n模块去安装多个指定版本的Node.js&#xff0c;并使用命令随时切换。 node中的n模块是&#xff0c;node专门用来管理node版本的模块&#xff0c;可以进行node版本的切换&#xff0c;下载&#xff0c;安装。 1.安装n npm install -g n 2.查看版本 n --version 3.展…