爬虫是在没有(用)API获取数据的情况下以Hack的方式获取数据的一种有效手段;进阶,就是从爬取简单页面逐渐过渡到复杂页面的过程。针对特定需求,爬取的网站类型不同,可以使用不同的python库相结合,达到快速抓取数据的目的。但是无论使用什么库,第一步分析目标网页的页面元素发现抓取规律总是必不可少的:有些爬虫是通过访问固定url前缀拼接不同的后缀进行循环抓取,有些是通过一个起始url作为种子url继而获取更多的目标url递归抓取;有些网页是静态数据可以直接获取,有些网页是js渲染数据需要构造二次请求……如果统统都写下来,一篇文章是不够的,这里举几个典型的栗子:
以从OPENISBN网站抓取图书分类信息为例,我有一批图书需要入库,但是图书信息不全,比如缺少图书分类,此时需要去openisbn.com网站根据ISBN号获取图书的分类信息。如《失控》这本书, ISBN: 7513300712 ,对应url为 http://openisbn.com/isbn/7513300712/,分析url规律就是以http://openisbn.com/isbn/作为固定前缀然后拼接ISBN号得到;然后分析页面元素作为固定前缀然后拼接ISBN号得到;然后分析页面元素,Chrome右键 —> 检查:直接使用urllib2 + re 来获得“Category:” 信息:import re
import urllib2
isbn = '7513300712'
url = '
category_pattern = re.compile(r'Category: *.*, ')
html = urllib2.urlopen(url).read()
category_info = category_pattern.findall(html)
if len(category_info) > 0 :
print category_info[0]
else:
print 'get category failed.'
输出:
Category: 现当代小说, 小说,
2.选择合适的定位元素:
由于页面中只有一行“Category:” 信息,正则表达式提取就行,如果有很多行的话就需要缩小查找范围了,BeautifulSoup库就可以用来定位查找范围。通过分析可知,包含所需“Category:” 最近一层的div 是
使用urllib2 + Beautiful Soup 3 + re 再来提取一次 (Beautiful Soup最新版本为4.4,兼容python3和python2,BS4跟BS3在导包方式上有点差别):import re,urllib2
from bs4 import BeautifulSoup
isbn = '7513300712'
url = 'http://openisbn.com/isbn/{0}/'.format(isbn)
category_pattern = re.compile(r'Category: *.*, ')
html = urllib2.urlopen(url).read()
soup = BeautifulSoup(html)
div_tag = soup.find('div',{'class':'Article'})
category_info = category_pattern.findall(str(div_tag))
if len(category_info) > 0 :
print category_info[0]
else:
print 'get category failed.'
输出:
Category: 现当代小说, 小说,
3. 抓取js渲染的内容:
用baidu搜索日历,获取结果页中的节假日日期
像上次一样直接使用urllib打开网页,发现返回的html中并没有期望得到的内容,原因是我通过浏览器所看到的页面内容实际是等js渲染完成后最终展现的,中间还包含了多次的ajax请求,这样使用urllib一次就不能胜任了,此时就可以让selenium上场了(webdriver用的phantomjs,需要提前下载phantomjs放到当前的PATH路径下),由于要查找的标识
import urllib
from selenium import webdriver
from BeautifulSoup import BeautifulSoup
holiday_list = []
url = 'http://www.baidu.com/s?' + urllib.urlencode({'wd': '日历'})
date_pattern = re.compile(r'date="[\d]+[-][\d]+[-][\d]+"')
driver = webdriver.PhantomJS()
driver.get(url)
html = driver.page_source
driver.quit()
soup = BeautifulSoup(html)
td_div_list = soup.findAll('div',{'class':'op-calendar-new-relative'})
for td_tag in td_div_list:
href_tag = str(td_tag.a)
if href_tag.find('休') != -1:
holiday_date_list = date_pattern.findall(href_tag)
if len(holiday_date_list) > 0:
holiday_list.append(holiday_date_list[0].split('"')[1])
print holiday_list
输出:
['2016-4-2', '2016-4-3', '2016-4-4', '2016-4-30', '2016-5-1’]
4. 设置代理,抓取google play排行榜
selenium不仅可以很好的模拟浏览器行为,还可以将网页内容截图保存from selenium import webdriver
url = 'https://play.google.com/store/apps/top?hl=zh_CN'
proxy_setting = ['--proxy=127.0.0.1:10800', '--proxy-type=socks5']
driver = webdriver.PhantomJS(service_args=proxy_setting)
driver.get(url)
driver.maximize_window()
# driver.implicitly_wait(10)
top_group_list = driver.find_elements_by_css_selector('.id-cluster-container.cluster-container.cards-transition-enabled')
driver.get_screenshot_as_file('top.jpg’)
for top_group in top_group_list:
group_name = top_group.find_element_by_xpath('div/div[@class="cluster-heading"]/h2/a').text
for item in top_group.find_elements_by_class_name('title'):
print u'bound: {0} app: {1}'.format(group_name,item.text)
driver.quit()
原文链接:https://www.zhihu.com/question/35461941/answer/99930298