现在网络爬虫有很多方式可以写,比如node.js或者go, 甚至php都行,我之所以选择python的原因是因为教程多,可以系统学习,因为光懂得使用html选择器来爬去页面是不够的,我还要想学习一些爬虫过程中常见的坑,以及一些注意事项,比如修改浏览器的header之类的小技巧。
代码注释都很详细了,其实只要直接阅读源码即可。
这个爬虫的目的很简单,爬去某个房产网站的楼盘名字+价格+1张图片的下载(单纯测试文件下载功能),以备之后分析房价走势而用,为了不给对方服务器增加太多压力,我只选择了爬取3个页面。
我这里说说几个需要注意的知识点吧:
#记得修改发送的headers听说默认发送过去的都是带有python信息的头,很容易被对方网站检查出是一个爬虫机器人,导致ip被封,所以最好让自己的爬虫程序像人类一点,但是这个代码只能起到一般的隐瞒,真的有网站想防止爬虫,你也是骗不过的,上代码:
headers = {“user-agent”:”mozilla/5.0 (macintosh; intel mac os x 10_9_5) applewebkit 537.36 (khtml, like gecko) chrome”,
“accept”:”text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8″},
#html的选择器,我采用pyquery而不是beautifulsoup很多书都推荐beautifulsoup,但是作为一个习惯了jquery的人来说,beautifulsoup的语法实在是有点拗口,而且貌似还不支持:first-child等高级复杂的css选择器模式,或者支持,但是我没找到,也不是很仔细看文档。
然后我网上找了一下资料,发现很多人推荐pyquery这个库,自己下来用了一下,发现真的很舒服,所以果断采用了。
#爬虫思路思路其实很简单:1.找到某个房产的列表页,分析第二第三页的url结构;2.获取每一个列表页的所有列表条目信息的url,存入python的set()集合中,之所以用set,是为了去掉重复的url信息。3.通过获取的房子的url,进入详情页,再爬去有价值的字段信息,比如图片文字之类的。4.目前我只进行简单的print数据而已,没有把获取的数据存为本地的json或者csv格式,这个之后做吧,to be done.
下面是全部代码代码:
#获取页面对象
from urllib.request import urlopen
from urllib.request import urlretrieve
from pyquery import pyquery as pq
#修改请求头模块,模拟真人访问
import requests
import time
#引入系统对象
import os
#你自己的配置文件,请将config-sample.py重命名为config.py,然后填写对应的值即可
import config
#定义链接集合,以免链接重复
pages = set()
session = requests.session()
baseurl = ‘http://pic1.ajkimg.com’
downloaddir = ‘images’
#获取所有列表页连接
def getallpages():
pagelist = []
i = 1
while(i < 2):
newlink = 'http://sh.fang.anjuke.com/loupan/all/p' + str(i) + '/'
pagelist.append(newlink)
i = i + 1
return pagelist
def getabsoluteurl(baseurl, source):
if source.startswith("http://www."):
url = "http://"+source[11:]
elif source.startswith("http://"):
url = source
elif source.startswith("www."):
url = "http://"+source[4:]
else:
url = baseurl+"/"+source
if baseurl not in url:
return none
return url
#这个函数内部的路径按照自己的真实情况来写,方便之后的数据导入
def getdownloadpath(baseurl, absoluteurl, downloaddirectory):
path = absoluteurl.replace("www.", "")
path = path.replace(baseurl, "")
path = downloaddirectory+path
directory = os.path.dirname(path)
if not os.path.exists(directory):
os.makedirs(directory)
return path
#获取当前页面的所有连接
def getitemlinks(url):
global pages;
#先判断是否能获取页面
try:
req = session.get(url, headers = config.value['headers'])
#这个判断只能判定是不是404或者500的错误,如果dns没法解析,是无法判定的
except ioerror as e:
print('can not reach the page. ')
print(e)
else:
h = pq(req.text)
#获取第一页的所有房子模块
houseitems = h('.item-mod')
#从模块中提取我们需要的信息,比如详情页的url,价格,略缩图等
#我倾向只获取详情页的url,然后在详情页中获取更多的信息
for houseitem in houseitems.items():
houseurl = houseitem.find('.items-name').attr('href')
#print(houseurl)
pages.add(houseurl)
#获取详情页的各种字段,这里可以让用户自己编辑
def getitemdetails(url):
#先判断是否能获取页面
try:
req = session.get(url, headers = config.value['headers'])
#这个判断只能判定是不是404或者500的错误,如果dns没法解析,是无法判定的
except ioerror as e:
print('can not reach the page. ')
print(e)
else:
time.sleep(1)
h = pq(req.text)
#get title
houseprice = h('h1').text() if h('h1') != none else 'none'
#get price
houseprice = h('.sp-price').text() if h('.sp-price') != none else 'none'
#get image url
houseimage = h('.con a:first-child img').attr('src')
houseimageurl = getabsoluteurl(baseurl, houseimage)
if houseimageurl != none:
urlretrieve(houseimageurl, getdownloadpath(baseurl, houseimageurl, downloaddir))
# if bsobj.find('em',{'class','sp-price'}) == none:
# houseprice = 'none'
# else:
# houseprice = bsobj.find('em',{'class','sp-price'}).text;
# if bsobj.select('.con a:first-child .item img')== none:
# housethumbnail = 'none'
# else:
# housethumbnail = bsobj.select('.con a:first-child .item img');
#start to run the code
allpages = getallpages()
for i in allpages:
getitemlinks(i)
#此时pages 应该充满了很多url的内容
for i in pages:
getitemdetails(i)
#print(pages)