微信怎么提现到中国农业银行微信提现

2562人阅读
Python(15)
利用爬虫获取豆瓣上可能喜欢的书籍
标签: 爬虫 Python
博主比较喜欢看书,购物车里面会放许多书,然后等打折的时候开个大招。然而会遇到一个问题,就是不知道什么书是好书,不知道一本书到底好不好,所以常常会去豆瓣读书看看有什么好书推荐,不过这样效率比较低。最近学习了爬虫的基础知识,有点手痒,故写一个爬取豆瓣推荐书籍的爬虫,和大家分享一下。
我们给爬虫设置一个起始url,然后爬取豆瓣在该url推荐的书籍及推荐书籍的推荐书籍……直到达到预设的爬取次数或者某个终止条件。
由于篇幅有限,不可能讲解太多的基础知识,如果大家觉得理解有困难的话,可以看看慕课网的视频,这个视频非常的赞。
2.爬虫框架
爬虫一共有5个模块:调度器,url管理器,html下载器,html解析器和html输出器。
爬虫调度器通过调度其它的模块完成任务,上面推荐的视频中有一张非常棒的图说明了爬虫通过调度器运行的流程:
其中的应用模块对应的是输出器,解释一下运行流程:
(1) 调度器查询是否有未爬取的url
(2) 如果“无”则跳转至(8),如果“有”则获取一个url
(3) 下载器根据获取的url下载html数据
(4) 解析器解析下载的html数据,获得新的url和有价值数据
(5) 调度器将获得的url传递给url管理器
(6) 调度器将获得的有价值数据传递给输出器
(7) 跳转至(1)
(8) 将输出器中的有价值数据全部输出
3.爬虫实现
3.1 url管理器实现
url管理器对未爬取和已爬取的url进行管理,记录未爬取的url是为了对新的网页进行爬取,记录已爬取的url是为了防止爬取已经爬取过的网页。
url管理器中有2个集合,分别记录未爬取和已爬取的url。
url管理器中有4种方法,详见代码注释:
class UrlManager(object):
def __init__(self):
self.new_urls = set()
self.old_urls = set()
def add_new_url(self, url):
if url is None:
if url not in self.new_urls and url not in self.old_urls:
self.new_urls.add(url)
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
for url in urls:
self.add_new_url(url)
def has_new_url(self):
return len(self.new_urls) != 0
def get_new_url(self):
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
3.2 html下载器实现
html下载器根据传入的url下载网页的html数据。
下载器需要用到urllib2库,这个库是Python编写爬虫时常用的库,具有根据给定的url获取html数据,伪装成浏览器访问网页,设置代理等功能。由于我们获取的是豆瓣的推荐书籍,不需要登录,所以只使用根据url获取html数据的功能即可。
需要注意的是,豆瓣是个很不错的网站,所以可能有很多的爬虫在爬取豆瓣,因此豆瓣也有很多的反爬虫机制,最直接的反爬虫机制就是禁制程序访问豆瓣,因此我们的爬虫要伪装成浏览器进行页面爬取。
import urllib2
class HtmlDownloader(object):
def download(self, url):
if url is None:
return None
request = urllib2.Request(url)
request.add_header('user-agent', 'Mozilla/5.0')
response = urllib2.urlopen(request)
except urllib2.URLError, e:
if hasattr(e,"code"):
print e.code
if hasattr(e,"reason"):
print e.reason
if response.getcode() != 200:
return None
return response.read()
3.3 html解析器实现
解析器解析下载的html数据,获得新的url和有价值数据,该模块是爬虫最麻烦的模块。
解析器需要用到BeautifulSoup和re库。
BeautifulSoup是用Python写的一个HTML/XML的解析器,可以很方便的从HTML/XML字符串中提取信息。
re是Python默认的正则表达式模块,提供正则表达式相关的操作。
3.3.1 parser()方法实现
解析器对外部只提供一个方法parser,该方法调用内部的两个方法实现解析功能:
from bs4 import BeautifulSoup
class HtmlParser(object):
def parse(self, page_url, html_cont):
if page_url is None or html_cont is None:
soup = BeautifulSoup(html_cont, 'html.parser', from_encoding='utf-8')
new_urls = self._get_new_urls(soup)
new_data = self._get_new_data(page_url, soup)
return new_urls, new_data
3.3.2 _get_new_urls()方法实现
内部方法_get_new_urls()从传递的beautifulsoup对象中提取url信息,那么到底提取的哪个部分的url?我们以豆瓣页面为例子进行讲解。
打开该页面,在“喜欢读‘代码大全(第2版)’的人也喜欢”处(即1处)点击鼠标右键,审查元素,这时会在浏览器下方弹出网页代码,不过我们要的不是这个标题,将鼠标移动到其父结点处(即2处),会发现推荐的书籍都被蓝色覆盖了,即&div id="db-rec-section" class="block5 subject_show knnlike"&包含的url都是我们要提取的url。
在设计模式处点击鼠标右键,审查元素,可以看到《设计模式》的url为/subject/1052241/,使用同样的方法可以查看到其他书籍的url,这些url的前缀都是一样的,不同只是最后的数字不一样,且这些数字或为7位,或为8位,因此推荐书籍url的正则表达式可以写为"https://book\.douban\.com/subject/\d+/$"
内部方法_get_new_urls()的实现代码如下:
def _get_new_urls(self, soup):
new_urls = set()
recommend = soup.find('div', class_='block5 subject_show knnlike')
links = recommend.find_all('a', pile(r"https://book\.douban\.com/subject/\d+/$"))
for link in links:
new_url = link['href']
new_urls.add(new_url)
return new_urls
一些说明:
find()与find_all()查找的是符合其括号中条件的结点,如上面第4行代码表示查找标签为div,class值为block5 subject_show knnlike的结点。由于class是Python中的保留字,所以find()中加了一个下划线即class_
find()是在html中寻找第一个符合条件的结点,这里的&div id="db-rec-section" class="block5 subject_show knnlike"&是唯一的,所以请放心使用find()
find_all()是在html中寻找所有的符合条件的结点
使用正则表达式的时候,前面加了一个字母r,表示字符串是“原生的”,不需要进行字符串转义,直接写正则表达式就行了。如果不加字母r,特殊符号在正则表达式中转义一次,在字符串中转义一次,写起来就十分的麻烦
3.3.3 _get_new_data()方法实现
作为一个读者,关注的主要信息就是书名,评分,作者,出版社,出版年,页码以及价钱,其他的基本就不考虑了。因此我们就提取以上列举的信息。
用审查元素的方法提取书名,发现包含书名的结点为&span property="v:itemreviewed"&代码大全(第2版)&/span&
用审查元素的方法提取评分,发现包含评分的结点为&strong class="ll rating_num " property="v:average"& 9.3 &/strong&
用审查元素的方法提取作者等基本信息,发现所有的信息都是&div id="info" class=""&结点的子结点
书名和评分直接使用find()找到相关结点,然后使用.string方法提取结点的内容,但是书本的基本信息这样就不行了,因为作者,出版社等结点的标签是一样。怎么办?既然我们想提取的就是作者,出版社等信息,那么直接根据结点内容搜索。
首先找到&div id="info" class=""&结点,然后在该结点中使用find(text='出版社')找到内容为“出版社”的结点,我们想要的“电子工业出版社”就是该结点的下一个结点,使用next_element就可以访问当前结点的下一个结点,got it!
内部方法_get_new_data()的实现代码如下:
def _get_new_data(self, page_url, soup):
res_data = {}
res_data['url'] = page_url
res_data['bookName'] = soup.find('span', property='v:itemreviewed').string
res_data['score'] = soup.find('strong', class_='ll rating_num ').string
&div id="info" class=""&
&span class="pl"& 作者&/span&:
&a class="" href="/search/Steve%20McConnell"&Steve McConnell&/a&
&/span&&br&
&span class="pl"&出版社:&/span& 电子工业出版社&br&
&span class="pl"&出版年:&/span& 2007-8&br&
&span class="pl"&页数:&/span& 138&br&
&span class="pl"&定价:&/span& 15.00元&br&
info = soup.find('div', id='info')
res_data['author'] = info.find(text=' 作者').next_element.next_element.string
res_data['publisher'] = info.find(text='出版社:').next_element
res_data['time'] = info.find(text='出版年:').next_element
res_data['price'] = info.find(text='定价:').next_element
res_data['intro'] = soup.find('div', class_='intro').find('p').string
return None
if res_data['intro'] == None:
return None
return res_data
一些说明:
有的页面没有“出版社”,“价格”等信息,评分高的书籍信息都是完整的,故使用tyr-except将这些页面舍弃
有的页面有“简介”标签,但是没有简介,目前发现这种情况的都是旧版不再印刷的书,故使用tyr-except将这些页面舍弃
3.4 html输出器实现
输出器保存已经爬取页面的有价值信息,然后在脚本结束时将这些信息以较为友好的html格式输出。
输出器将所有的信息保存在一个列表里面,保存数据方法的代码如下:
class HtmlOutputer(object):
def __init__(self):
self.datas = []
def collect_data(self, data):
if data is None:
self.datas.append(data)
数据以html格式输出既简单又方便,我们可以先用nodepad++编写自己想要的html格式,然后使用浏览器打开观察,不断的改进,最终得到自己想要的数据展现形式,我的html格式如下:
&&GoodBooks&&
& href='/subject/1477390/' target=_blank&代码大全(第2版)&&
border="1"&
&&评分:&&&9.3&&&
&&作者:&&[美] 史蒂夫·迈克康奈尔&&
&&定价:&&128.00元&&
&&出版社:&&电子工业出版社&&
&&出版时间:&&2006-3&&
简介:第2版的《代码大全》是著名IT畅销书作者史蒂夫·迈克康奈尔11年前的经典著作的全新演绎:第2版不是第一版的简单修订增补,而是完全进行了重写;增加了很多与时俱进的内容。这也是一本完整的软件构建手册,涵盖了软件构建过程中的所有细节。它从软件质量和编程思想等方面论述了软件构建的各个问题,并详细论述了紧跟潮流的新技术、高屋建瓴的观点、通用的概念,还含有丰富而典型的程序示例。这本书中所论述的技术不仅填补了初级与高级编程技术之间的空白,而且也为程序员们提供了一个有关编程技巧的信息来源。这本书对经验丰富的程序员、技术带头人、自学的程序员及几乎不懂太多编程技巧的学生们都是大有裨益的。可以说,无论是什么背景的读者,阅读这本书都有助于在更短的时间内、更容易地写出更好的程序。
最后的&hr&是分割线,浏览器中的效果:
把具体的内容使用%s格式化输出即可,需要注意的是字符变量后面加上.encode('utf-8'),将字符的编码格式改为utf-8.
输出器的输出代码如下:
def output_html(self):
fout = open('GoodBooks.html', 'w')
fout.write('&html&')
fout.write('&meta charset="UTF-8"&')
fout.write('&title&GoodBooks_moverzp&/title&')
fout.write('&body&')
for data in self.datas:
print data['bookName'], data['score']
fout.write("&h2&&a href='%s' target=_blank&%s&/a&&/h2&" % (data['url'].encode('utf-8'), data['bookName'].encode('utf-8')))
fout.write('&table border="1"&')
fout.write('&tr&&td&评分:&/td&&td&&b&%s&/b&&/td&&/tr&' % data['score'].encode('utf-8'))
fout.write('&tr&&td&作者:&/td&&td&%s&/td&&/tr&' % data['author'].encode('utf-8'))
fout.write('&tr&&td&定价:&/td&&td&%s&/td&&/tr&' % data['price'].encode('utf-8'))
fout.write('&tr&&td&出版社:&/td&&td&%s&/td&&/tr&' % data['publisher'].encode('utf-8'))
fout.write('&tr&&td&出版时间:&/td&&td&%s&/td&&/tr&' % data['time'].encode('utf-8'))
fout.write('&/table&')
fout.write('&p&%s' % data['intro'].encode('utf-8'))
fout.write('&/p&&hr&')
fout.write('&/body&')
fout.write('&/html&')
3.5 调度器实现
调度器是爬虫的“大脑”,进行任务的分配。将第2节爬虫框架的步骤写成代码就实现了调度器。
以下是调度器的代码实现,以《代码大全》为起始url,抓取50个推荐书籍的信息:
import url_manager, html_downloader, html_parser, html_outputer
import time
class SpiderMain(object):
def __init__(self):
self.urls = url_manager.UrlManager()
self.downloader = html_downloader.HtmlDownloader()
self.parser = html_parser.HtmlParser()
self.outputer = html_outputer.HtmlOutputer()
def craw(self, root_url):
self.urls.add_new_url(root_url)
while self.urls.has_new_url():
new_url = self.urls.get_new_url()
print 'craw %d : %s' % (count, new_url)
html_cont = self.downloader.download(new_url)
new_urls, new_data = self.parser.parse(new_url, html_cont)
self.urls.add_new_urls(new_urls)
self.outputer.collect_data(new_data)
time.sleep(0.1)
if count == 50:
count += 1
print 'craw failed'
self.outputer.output_html()
if __name__ == "__main__":
root_url = "/subject/1477390/"
obj_spider = SpiderMain()
obj_spider.craw(root_url)
最终爬取的结果如下:
4.存在的问题
Q1:url管理器中使用set()保存未爬取的url,获取新的url时,使用的是pop()方法,该方法是随机从集合中取出一个元素并删除。这可能会导致我们我们爬取的书籍与我们设置的第一个url相去甚远,最极端的情况是每次得到的url都是推荐书籍中相似度最低的书籍,那么爬不了几次获取的信息都是“垃圾信息”。
解决方法:使用队列保存未爬取的url,这样爬取的轨迹就是以初始url为中心均匀扩散。
Q2:不设置抓取页面的次数,在700次左右会发生403Forbidden错误。
解决方法:八成是豆瓣检测到了爬虫,然后把IP封了。可以使用IP代理的方法防止IP被封。
5.可以做的改进
保存已爬取和未爬取的url到文件或者数据库,可以实现断点爬取
按照评分和推荐层级对爬取的结果进行排序,将可能喜欢的评分更高的书放在前面
本文爬取的数据比较少,所以就直接放在内存中,如果要爬取较多的数据,可以每爬取1条或者n条后,将数据存储在文件或数据库中
当需要做大量数据爬取的时候,可以使用多线程加快速度
增加简单的GUI
源码在我的,本节代码只是一个最初版本,会不断的完善的
本文爬虫的框架有5个模块/文件:调度器,url管理器,下载器,解析器和输出器
爬虫框架是最重要,本文的爬虫比较简单,框架是自己写的,但是在较大型的应用中可能就捉襟见肘了,推荐第三方的爬虫框架Scrapy
主要的库有3个:urllib2, BeautifulSoup,re
服务器的反爬虫和爬虫一直在互相斗争,爬虫代码一般都有时效性,如果网站html代码变化了,爬虫的解析器就得重写
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:54193次
积分:1169
积分:1169
排名:千里之外
原创:56篇
评论:89条
(1)(1)(2)(1)(4)(8)(1)(11)(14)(10)(3)(1)(良辰讵可待)
第三方登录:本帖最后由 zsl_8087 于
16:19 编辑
本人小白一枚,今天初次使用集搜客软件用于抓取数据,碰到一些问题望情大神们帮助,在此感激不尽,说下问题:
手里有几千万个企业名称,想以此为索引获取其企业信用信息(天眼查),查询格式如下:
& && &/search?key=北京百度网讯科技有限公司&checkFrom=searchBox
QQ截图05.png (123.74 KB, 下载次数: 3)
16:03 上传
列表item XPATH为://*[@class='search_result_single ng-scope']
由于详情页的一些信息空缺需先抓取上图红色框内的HTML后再执行点击跳转详情页。
详情页方面由于链接是点击新开页面展示出来,链接也是没有规律的ID字符串,如:/company/22822
详情页所需信息为下图红色框:
QQ截图45.png (592.89 KB, 下载次数: 5)
16:11 上传
其上下XPATH分别为://*[@class='row b-c-white ']& & 和& & //*[@class='row b-c-white company-content']
现在问题来了,集搜客只支持翻页和当前页面跳转,像这种另开页面的需要开启飞掠模式~,全程不需要任何图片。,本人新手上路第一天就翻车了还是说我不够熟悉不知道另外的办法,在此特向各位大神请求帮助,望能解答。再次感谢。
PS:说可以花钱解决的就算了,可以的话就不需要自己钻研了,另一半也算给自己提升的机会。
从列表到详情页 有独立网址 直接抓取href做层级线索就可以 不需要用飞掠模式
从列表到详情页 有独立网址 直接抓取href做层级线索就可以 不需要用飞掠模式
从列表到详情页 有独立网址 直接抓取href做层级线索就可以 不需要用飞掠模式 ...
层级线索?能一次性抓完完整的么?不是说先保存下来详情页链接再抓详情页的方式。而且层级线索不是只能抓翻页之类的当前页刷新的方式么?
层级线索?能一次性抓完完整的么?不是说先保存下来详情页链接再抓详情页的方式。而且层级线索不是只能抓 ...
层级不只能抓翻页,因为你这个详情页有独立的网址,可以把这个网址当做下级线索,然后做一个下级规则来抓取详情页的内容
层级线索?能一次性抓完完整的么?不是说先保存下来详情页链接再抓详情页的方式。而且层级线索不是只能抓 ...
用纯粹的层级抓取,速度最快,根本不用飞掠模式。参看。
层级不只能抓翻页,因为你这个详情页有独立的网址,可以把这个网址当做下级线索,然后做一个下级规则来抓 ...
我再试试,谢谢
用纯粹的层级抓取,速度最快,根本不用飞掠模式。参看层级抓取教程。
谢谢,我再试试
谢谢,我再试试
楼主现在解决了吗?&&是怎么做的?
楼主现在解决了吗?&&是怎么做的?
就用《》和《就可以采集了
知乎话题结构分析今日头条热点新闻采集【第52期】赶集网、58同城、房天下房源采集【第51期】安居客、链家、Q房网房源采集【第50期】微博话题、粉丝、评论转发采集【第49期】
12345678910
Fuller帖子:3899 ym帖子:1430 xandy帖子:1055

我要回帖

更多关于 微信提现不到账怎么办 的文章

 

随机推荐