最近一直在联系爬虫,所以对一些网站抓取信息是遇到了问题,这里总结一下我爱我家的问题
在以往的练习时,xpath是我最常用的方法,这次也不例外
好的,我们开始爬取数据
第一步 ,接口查找
我们需要按照不同区域爬取,增加一点难度
第一个问题,我们在爬取时会第一步就遇到了界面访问不进去的问题
访问进去是一个空界面,或者根本访问不进去,
但是有些时候,我们还能访问进去,感觉上是随机的,比较烦
第二个问题
访问进去之后再进行数据爬取时有些数据为空,或者找不到,
这个问题我们可以写一个判空函数来决绝,
给大家看一下截图
那么我们如何解决的第一个问题呢,我们这里写了一个反复访问的函数,可能一次访问不进去,但是两次,三次呢
给大家看一下代码
import requests
from lxml import etree
import time
import re
import threading
from queue import Queue
house_data = {
'图片链接':'',
'标题': '',
'房屋信息': '',
'地址': '',
'访问动态': '',
'标签': '',
'价格': '',
'出租方式': '',
}
class Wawj(threading.Thread):
# 初始化
def __init__(self, name, url_queue):
threading.Thread.__init__(self)
# 拿到任务队列
self.url_queue = url_queue
self.name = name
def iskong(self, temp_list):
if len(temp_list) > 0:
return temp_list[0]
else:
return ''
def run(self):
while True:
# 线程停止条件
if self.url_queue.empty():
break
else:
url = self.url_queue.get()
print("取值:",url)
print(self.name, '取出的任务是:', url)
self.get_content(url=url)
# print(self.name, '完成任务页码是:', url)
def get_content(self,url):
##给四次机会
content = self.request_url(url=url)
times =4
while times > 0:
if '<title>' in content:
content = content
else:
pattern = re.compile(r'<script>.*?href=\'(.*?)\';')
href = pattern.findall(content)[0]
content = self.request_url(href)
times -= 1
print(times)
self.get_data(content)
# print(content)
return content
def request_url(self,url):
headers = {
'Cookie': 'PHPSESSID=qhu7e2m8q2qe88r85slgensh92; _ga=GA1.2.1363814418.1557303006; _gid=GA1.2.1393847228.1557303006; yfx_c_g_u_id_10000001=_ck19050816100612577584201493913; Hm_lvt_94ed3d23572054a86ed341d64b267ec6=1557303007; _Jo0OQK=3CD62F3642CABD4011F22C4A9159FB3A22425BFB3D220139C0679F361E7C08A30EA36E358C8BA464C45028D459BDDFCFBE183E96C00A59DFD84EB50F436F358AF15C57212F12283777C840763663251ADEB840763663251ADEB11EC4D4E6CBC2C3E9C0616B90758FB61GJ1Z1ew==; domain=bj; yfx_f_l_v_t_10000001=f_t_1557303006247__r_t_1557303006247__v_t_1557317859010__r_c_0; Hm_lpvt_94ed3d23572054a86ed341d64b267ec6=' + str(time.time()),
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
}
response = requests.get(url,headers=headers).content.decode('utf-8')
content1 = response
return content1
def get_data(self,response):
try:
# pass
tree = etree.HTML(response)
total_list = tree.xpath('//div[@class="list-con-box"]/ul[@class="pList"]/li')
# print(total_list) #有值
num = 1
for total in total_list:
# try:
#图片链接
picHerf = total.xpath('.//img[@class="lazy"]/@src | .//img[@class="lazy"]/@data-src')
picHerf =self.iskong(picHerf)
# print(picHerf)
#标题
title = total.xpath('.//div[@class="listCon"]/h3/a/text()')
title = self.iskong(title)
#信息
info = total.xpath('.//div[@class="listX"]/p[position()<2]/text()')
info = info[0].replace(" ", "")
#地址
addr = total.xpath('.//div[@class="listX"]/p/a/text()')
addr = self.iskong(addr)
#查看动态
dynamic = total.xpath('.//div[@class="listX"]/p[last()]/text()')
if len(dynamic) > 1:
dynamic = dynamic[1]
else:
dynamic = "暂无信息"
#标签
lable = total.xpath('.//div[@class="listTag"]/span/text()')
if len(lable) == 0:
lable = "暂时无值"
else:
lable = ' '.join(lable)
#价格
price = total.xpath('.//div[@class="jia"]/p//text()')
price = self.iskong(price)
#出租方式
Rentway = total.xpath('.//div[@class="jia"]/p/text()')
if len(Rentway) > 1:
Rentway = Rentway[1]
else:
Rentway = '暂无出租信息'
house_data['图片链接'] = picHerf
house_data['标题'] = title
house_data['房屋信息'] = info
house_data['地址'] = addr
house_data['访问动态'] = dynamic
house_data['标签'] = lable
house_data['价格'] = price
house_data['出租方式'] = Rentway
num += 1
list_data = [{"num": num, "house_data": house_data}]
with open('5i5j.txt', 'a', encoding='utf-8') as f:
f.write(str(list_data) + '\n')
f.write('==================' + '\n')
except:
pass
# pattern = re.compile(r'<script>.*?href=\'(.*?)\';')
# hreferror = pattern.findall(content)[0]
# with open('job.txt', 'a', encoding='utf-8')as fp:
# fp.write(hreferror+'\n')
if __name__ == '__main__':
# 任务开始时间
start_time = time.time()
# 创建队列任务
# ['chaoyangqu/', 'haidianqu/', 'dongchengqu/', 'xichengqu/', 'fengtaiqu/', 'shijingshanqu/', 'tongzhouqu/',
# 'changpingqu/', 'daxingqu/', 'yizhuang/', 'shunyiqu/', 'fangshanqu/', 'mentougou/', 'pinggu/', 'huairou/',
# 'miyun/', 'yanqing/']
url_queue = Queue()
href_list = [
('chaoyangqu', 227),('haidianqu',145),('dongchengqu',40),('xichengqu',83),('fengtaiqu',104),('shijingshanqu',23),
('tongzhouqu',68),('changpingqu',65),('daxingqu',44),('yizhuang',9),('shunyiqu',30),('fangshanqu',59),('mentougou',1)
# ,('pinggu',1),('huairou',),('miyun',),('yanqing',) #没有房源的地区
] # 第一个为区域名,第二个为总页数
for i in href_list:
for j in range(1, i[1] + 1):
url = 'https://bj.5i5j.com/zufang/{}/n{}/'.format(i[0], j)
url_queue.put(url)
# 2 生成线程
craw1_name = ['c1', 'c2', 'c3']
craw1_tread = []
for name in craw1_name:
crawl = Wawj(name, url_queue)
crawl.start()
craw1_tread.append(crawl)
#join 阻塞线程,让子线程都完成任务后,主线程再往下进行
for thread in craw1_tread:
thread.join()
# 任务结束时间
end_time = time.time()
# 需要时间
print(end_time - start_time)
在这里我们做了一个路径拼接,将所有的区域链接拿到,可以省下一次访问,同时找到确定的页数,不要写死循环,避免跳不出来