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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

300 KVA(240kW、180KVAR)系列负载组

交流 固定式/永久式 电阻式和电抗性 300 KVA&#xff08;240kW、180KVAR&#xff09; 480 伏交流电 60赫兹 这是一款紧凑、多功能的 300 KVA 固定/永久负载组&#xff0c;用于测试备用发电机和地面电源装置。负载组可用于测试在 480V 电压下最大 300KVA 的任何负载。…

可穿戴式手持气象仪

TH-SQ17在快节奏的现代生活中&#xff0c;我们越来越依赖各种智能设备来辅助我们的决策和行动。其中&#xff0c;气象信息的重要性不言而喻&#xff0c;它不仅关系到我们的出行安全&#xff0c;更影响着我们的日常生活安排。如今&#xff0c;一款革命性的产品——可穿戴式手持气…

Qt 实战(6)事件 | 6.1、事件机制

文章目录 一、事件1、基本概念2、事件描述3、事件循环4、事件分发4.1、QApplication::notify()4.2、QObject::event() 5、事件传递6、事件处理器 前言&#xff1a; Qt 框架中的事件机制&#xff08;Event Mechanism&#xff09;是一种核心功能&#xff0c;它允许应用程序以事件…

文华WH7主图多空预警系统指标公式源码

RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;//收盘价与N周期最低值做差&#xff0c;N周期最高值与N周期最低值做差&#xff0c;两差之间做比值定义为RSV K:SMA(RSV,3,1);//RSV的移动平均 D:SMA(K,3,1);//K值的移动平均 DIFF : EMA(CLOSE,12) - EMA(CLOSE,26); D…

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

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

考研数学一有多难?130+背后的残酷真相

考研数学一很难 大家平时在网上上看到很多人说自己考了130&#xff0c;其实这些人只占参加考研数学人数的极少部分&#xff0c;有个数据可以展示出来考研数学到底有多难&#xff1a; 在几百万考研大军中&#xff0c;能考到120分以上的考生只有2%。绝大多数人的分数集中在30到…

Lua流媒体服务器支持(MP4视频、桌面直播、摄像头)

本来在做FFMPEG的项目&#xff0c;忽然想到Lua封装FFMPEG与SRS实现一个简易的直播网站何尝不是一个大胆的想法。 示例为初级版本&#xff0c;主要是用来验证可行性和功能性DEMO 演示效果&#xff1a; Lua流媒体直播服务器(支持MP4、桌面直播、摄像头)_哔哩哔哩_bilibili 代码简…

【SSM】医疗健康平台-用户端-体检预约

知识目标 了解FreeMarker&#xff0c;能够简述FreeMarker的作用和生成文件的原理 熟悉FreeMarker的常用指令&#xff0c;能够在FTL标签中正确使用assign指令、include指令、if指令和list指令 掌握显示套餐列表功能的实现 掌握显示套餐详情功能的实现 掌握体检预约功能的实现…

【源码】最新源支付系统源码 V7版全开源 免授权 附搭建教程

最新源支付系统源码_V7版全开源_免授权_附详细搭建教程_站长亲测 YPay是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。它采用全新轻量化的界面UI&#xff0c;让您能更方便快捷地解决知识付费和运营赞助的难题。同时&#xff0c;它基于高性能的thin…

el-form重置后input无法输入问题

新增用户遇到的问题&#xff1a; 如果你没有为 formData 设置默认值&#xff0c;而只是将其初始化为空对象 {}&#xff0c;则在打开dialog时&#xff0c;正常输入&#xff0c; formdata会变成如下 但是&#xff0c;打开后&#xff0c;直接使用 resetFields 或直接清空表单&…

宜搭低代码开发高级认证例题1-待办列表

1、进行中待办和已完成待办界面相同 关键代码就是重要度默认为1星 2、新增自定义页面Todolist 2.1主要参数设置-新建远和API getTodoList和getDoneList代码相同 绑定代码&#xff1a;/${window.pageConfig.appType || window.g_config.appKey}/v1/form/searchFormDatas.json …

福州代理记账服务财务专业知识会计助手

福州的代理记服务可探索企业和个体工商户处理财务和会计工作。选择合适的代理记服务不仅可以节省成本&#xff0c;还可以确保财务工作专业、合规。以下是一些关于代理记服务的关键信息和财务信息&#xff0c;供您参考&#xff1a; https://www.9733.cn/news/detail/180.html …

C++ ─── vector的实现

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

【数据结构与算法】堆排序算法 详解

堆排序算法 Status heapAdjust(ElemType *a, int s, int m) {ElemType t a[s];for (int j s * 2 1; j < m; j j * 2 1) {if (j < m && a[j] < a[j 1]) {j;}if (t > a[j]) {break;}a[s] a[j];s j;}a[s] t;return OK; }Status heapSort(ElemType *a…

xhs 旋转验证码剖析和协议算法实现

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#…

计算机视觉的职业规划

Hi&#xff0c;大家好。我是茶桁。 今天这节课呢&#xff0c;咱们先不着急讲原理&#xff0c;先来讲讲职业规划的话题。 如果想要直接上手企业级的 AI 项目&#xff0c;可以看看咱们的「AI 人工智能企业项目实战」。 趋势和薪资 首先&#xff0c;先来讲讲就业的趋势。其实学…

JavaWeb——MySQL:DDL

目录 3. DQL:查询 ​编辑3.3 排序查询&#xff08;order by&#xff09; &#xff08;1&#xff09;排序 &#xff08;2&#xff09;多字段排序&#xff1a; &#xff08;3&#xff09;总结&#xff1a; 3. DQL:查询 查询是使用最多、最频繁的操作&#xff0c;因为前面的…

开心汉化轻量级工单与知识库一体化管理系统源码

开心汉化发布&#xff1a;轻量级工单与知识库一体化管理系统源码 我们很高兴地宣布&#xff0c;开心汉化团队现已发布一款轻量级工单与知识库一体化管理系统的汉化源码。该系统不仅功能强大&#xff0c;而且易于部署和管理&#xff0c;适用于各类企业或个人管理大量工单数据的…

微软结束将数据中心置于海底的实验

2016 年&#xff0c;微软 宣布了一项名为"纳蒂克项目"&#xff08;Project Natick&#xff09;的实验。基本而言&#xff0c;该项目旨在了解数据中心能否在海洋水下安装和运行。经过多次较小规模的测试运行后&#xff0c;该公司于 2018 年春季在苏格兰海岸外 117 英尺…

密码学及其应用 —— Java中的安全性

1. 简介 Java是一种广泛使用的编程语言&#xff0c;特别是在企业级解决方案中&#xff0c;比如使用J2EE、JavaBeans等技术。在Web开发领域&#xff0c;Java也有其应用&#xff0c;如客户端的applet和服务器端的Servlets/JSP。 1.1 Java的特点 面向对象&#xff1a;Java是一种面…