本文章的例子仅用于学习之用,如涉及版权隐私信息,请联系本人删除,谢谢。
最近一直在练习使用python爬取不同网站的信息,最终目的是实现一个分布式的网络爬虫框架,可以灵活适用不同的爬取需求。
项目github地址:
https://github.com/happyAnger6/anger6Spider
在学习的过程中遇到不少问题,在这里做一下总结,并分享出来,希望有兴趣的朋友批评指正,共同学习共同进步。
本着实用至上的目的,不准备过多讲实现细节和原理,直接通过项目需求来边实战边学习,因此本系列文章以解决问题为主。
本项目用到大量开源软件或框架,每节的例子开始部分会说明依懒于哪些开源库。python版本为3.4.0
依懒:
pip3 install tornado
pip3 install bs4
pip3 install selenium
phantomjs:一个无头浏览器,不是python包,而是一个软件,需要安装。
tornado:著名的web框架,使用它的目的主要是其对协程的良好支持以及异步http库,可以在单线程环境中充分提高性能。
bs4:beautifulsoup主要用于分析html页面,其强大功能不必多说。
selenium:本来是一个web自动测试化框架,由于其对多浏览器的支持,可以方便地处理页面中javascript等问题。
phantomjs:用来充当一个浏览器,用来解析javascript,实现动态点击页面等功能。
代码注释比较详细,不多说废话,直接上代码:
from bs4 import BeautifulSoup from tornado.httpclient import AsyncHTTPClient from tornado import gen from tornado.ioloop import IOLoop from selenium import webdriver import re url = "http://search.jd.com/Search?keyword=Python&enc=utf-8&book=y&wq=Python&pvid=33xo9lni.p4a1qb" def parse_info_from_soup(bs): items = bs.find_all("li",class_="gl-item") #查找所有class为"gl-item",标签名为li的标签 for item in items: #遍历所有标签 name = item.find("div",class_="p-name").find("em") #查找class为"p-name",标签名为div的标签,并查找em内容 price = item.find("div",class_="p-price").find("i") #查找价格 book_detail = item.find("span",class_="p-bi-store").find("a") #查找出版社 commit = item.find("div",class_="p-commit").find("a") #查找评论人数 print(name.text,book_detail.text,price.text,commit.text) print(len(items)) @gen.coroutine def main(): cli = AsyncHTTPClient() response = yield cli.fetch(url) #用tornado的AsyncHTTPClient来下载页面 bs = BeautifulSoup(response.body) #将页面信息转换为BeautifulSoup对象 print(bs) parse_info_from_soup(bs) #从页面中提取信息 def main1(): driver = webdriver.PhantomJS(executable_path="/usr/bin/phantomjs") driver.get(url) #通过无头浏览器PhantomJS下载页面 bs = BeautifulSoup(driver.page_source) #将页面信息转换为BeautifulSoup对象 parse_info_from_soup(bs) #从页面中提取信息 if __name__ == "__main__": IOLoop.instance().run_sync(main1)
直得注意的地方为main和main12个函数,分别运行可以看到得到的结果完全不同。
因为不使用PhantomJS的话,由于javascript的关系,页面无法完全加载,因此数据解析不出来。这也说明我们要针对不同的网站,采取不同的加载策略。
对于需要js动态加载的页面,我们需要使用PhantomJS;其它静态加载完成的可以使用AsyncHTTPClient。