资讯专栏INFORMATION COLUMN

记录一次用Python写爬虫的心得

james / 1031人阅读

摘要:前前后后弄了一个星期,看书写代码,我写出了一个基本能用的爬虫小代码,地址代码注释都很详细了,其实只要直接阅读源码即可。然后我网上找了一下资料,发现很多人推荐这个库,自己下来用了一下,发现真的很舒服,所以果断采用了。

现在网络爬虫有很多方式可以写,比如Node.js或者Go, 甚至PHP都行,我之所以选择Python的原因是因为教程多,可以系统学习,因为光懂得使用Html选择器来爬去页面是不够的,我还要想学习一些爬虫过程中常见的坑,以及一些注意事项,比如修改浏览器的Header之类的小技巧。

前前后后弄了一个星期,看书+写代码,我写出了一个基本能用的python爬虫小代码,github地址:https://github.com/qiujumper/...

代码注释都很详细了,其实只要直接阅读源码即可。

这个爬虫的目的很简单,爬去某个房产网站的楼盘名字+价格+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)

有问题欢迎和我讨论,这段代码还可以继续完善。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44283.html

相关文章

  • [新手开源] 爬取韩寒“一个”文章且自动邮件发送功能

    摘要:源码地址准备一台云服务器写好的脚本效果因为现在一个的客户端启动越来越慢,而且很多自己不感兴趣的东西我只是想看看文章,所以就写了这个小爬虫。因为一个是每天点会更新,所以自己的服务器要做一个定时服务,下自带了定时任务。 源码地址:https://github.com/xcc3641/pySendOneToEmail 准备 一台云服务器 写好的Python脚本 效果 因为现在一个的And...

    zhkai 评论0 收藏0
  • 12、web爬虫讲解2—Scrapy框架爬虫—Scrapy模拟浏览器登录—获取Scrapy框架Coo

    摘要:百度云搜索,搜各种资料搜网盘,搜各种资料模拟浏览器登录方法,可以返回一个请求给爬虫的起始网站,这个返回的请求相当于,返回的请求会替代里的请求请求,可以设置,回调函数表单提交,第一个必须参数,上一次响应的对象,其他参数,表单内容等可以将一个新 【百度云搜索,搜各种资料:http://www.bdyss.cn】 【搜网盘,搜各种资料:http://www.swpan.cn】 模拟浏览器登录...

    jay_tian 评论0 收藏0

发表评论

0条评论

james

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<